С плюсами и минусами каждого

Зрелость программиста определяется многими факторами, такими как знание алгоритмов, аналитическое мышление, фокусировка на общей картине, навыки отладки и т. Д. Кроме того, с моей точки зрения важны следующие два фактора:

  • Инженер-программист знает несколько подходов к решению одной и той же проблемы.
  • Инженер-программист выбирает подход на основе анализа его плюсов и минусов.

Чтобы помочь вам стать немного более зрелым, я собрал 5 способов клонирования объекта на C # и подготовил плюсы и минусы каждого из них.

Мы собираемся использовать два простых класса Person и Address во всех следующих примерах.

Но прежде чем мы начнем, я хочу напомнить вам о концепциях поверхностного и глубокого копирования в .NET. Неглубокая копия имеет свои собственные типы значений, но использует общие ссылочные типы с исходным объектом. Глубокая копия имеет собственные значения и ссылочные типы, то есть полностью отключена от исходного объекта. Инженер-программист может создать мелкую копию, просто вызвав метод MemberwiseClone, но глубокая копия требует написания некоторого дополнительного пользовательского кода.

Интерфейс ICloneable

Первый способ клонировать объект - просто реализовать интерфейс ICloneable, предоставляемый .NET. Этот интерфейс имеет единственный метод Clone, внутри которого мы должны вызвать метод MemberwiseClone класса Object.

Плюсы:

  • Нет необходимости определять собственный интерфейс.
  • Полный контроль над тем, что мы клонируем. Представьте, что класс Person включает свойство AccountHistory, которое используется для целей аудита. При клонировании объекта Person нам может потребоваться пустая история учетной записи. Такое требование можно выразить в коде следующим образом:

Минусы:

  • Метод Clone возвращает тип объекта. Вызывающий код должен привести объект к определенному типу данных.
  • Интерфейс ICloneable должен быть реализован для каждого класса, включенного в граф объектов.
  • Имена интерфейса или методов не указывают, какая копия возвращается вызывающей стороне - глубокая или неглубокая. Инженер-программист должен погрузиться в детали реализации.

🔔 Подпишитесь сейчас, чтобы не пропустить мои следующие статьи.

Пользовательский интерфейс IPrototype

Почему бы не создать собственный общий интерфейс вместо использования ICloneable? Наш настраиваемый интерфейс может исправить несколько проблем с ICloneable.

Давайте вызовем настраиваемый интерфейс IPrototype и определим внутри один метод CreateDeepCopy.

Плюсы:

  • Название метода CreateDeepCopy точно описывает его назначение.
  • Потребителям интерфейса IPrototype больше не нужно приводить тип возвращаемого значения метода CreateDeepCopy.
  • Полный контроль над тем, что мы клонируем, с интерфейсом ICloneable.

Минусы:

  • Интерфейс должен быть определен вручную инженером-программистом.
  • Интерфейс должен быть реализован для каждого класса, включенного в граф объектов.

Двоичная сериализация

Двоичная сериализация помогает клонировать объекты без реализации интерфейсов. Идея проста - сериализовать граф объекта в память, а затем десериализовать его обратно в объект.

Плюсы:

  • Больше не нужно реализовывать интерфейсы.
  • Каким бы сложным ни был объект, он будет полностью клонирован.
  • Логика клонирования существует в одном месте.

Минусы:

  • Class Person и все связанные с ним должны быть помечены атрибутом [Serializable].
  • Нет выбора между мелкими и глубокими копиями. При использовании сериализации для программиста доступна только опция глубокого копирования.

XML-сериализация

Сериализация XML - интересная альтернатива двоичной сериализации. Следующий пример кода очень похож на предыдущий с одной корректировкой одной строки:

Сериализация XML не требует атрибута [Serializable], что не может не радовать. Однако для сериализации XML требуется, чтобы каждый класс имел конструктор без параметров. Такое требование может показаться безобидным, но это не всегда так. Наличие конструктора без параметров в классе Person означает, что экземпляр может быть создан без имени, фамилии и т. Д. Я предпочитаю, чтобы все необходимые свойства были установлены во время создания объекта, чтобы избежать частично инициализированных объектов. Так что сериализация XML во многих случаях не сработает для меня.

Копировать конструктор

Конструктор копирования - это простой конструктор с одним параметром типа включающего класса. Внутри конструктора мы просто повторно инициализируем свойства объекта одно за другим.

Плюсы:

  • Полный контроль над тем, что мы клонируем.

Минусы:

  • Конструкторы копирования должны быть реализованы в каждом классе, включенном в граф объектов.

Последние мысли

Интерфейсы и конструкторы копирования дают программисту полный контроль над процессом клонирования. Методы клонирования на основе сериализации освобождают разработчика программного обеспечения от необходимости настраивать логику клонирования каждый раз, когда изменяется граф объекта.

Как всегда, серебряной пули нет, поэтому нам, программистам, необходимо тщательно анализировать каждый конкретный случай и выбирать наиболее подходящее решение с учетом его плюсов и минусов.

А теперь одна маленькая задача для вас, дорогой читатель: какой подход к клонированию я пропустил?

Спасибо за прочтение!

Больше шаблонов дизайна





Уровень кодирования

Спасибо, что стали частью нашего сообщества! Подпишитесь на наш канал YouTube или присоединитесь к Интервью по программированию Skilled.dev.