Реализация шаблона проектирования с помощью C#
Шаблоны проектирования можно считать набором возможных решений для конкретной проблемы, зарекомендовавшим себя в качестве оптимального варианта для определенных ситуаций. Другими словами шаблонами проектирования можно воспользоваться, столкнувшись с проблемой. Несомненно, по мере развития программирования множество других разработчиков, возможно, уже решали эту же проблему. Шаблон проектирования показывает наилучший способ решения повторяющейся проблемы. Использование шаблонов проектирования Создавая приложение, приходится много думать над тем, как программа будет вести себя при длительном выполнении. Очень трудно предсказать, как будет себя вести архитектура приложения, когда фактическое приложение будет реализовано полностью. Могут возникнуть проблемы, которые нельзя прогнозировать и которые могут появиться при создании программного обеспечения. Шаблоны проектирования помогают найти проверенную парадигму проектирования, которая станет надежной основой создаваемого проекта. Поэтому, следуя шаблону проектирования, можно легко предотвратить большинство проблем, возникающих при построении фактического проекта. Более того, шаблон проектирования упрощает понимание созданного кода другими архитекторами. История шаблонов проектирования Когда речь идет о термине "шаблон проектирования", первое, что может прийти в голову — это классическая книга по шаблонам проектирования "Gangs of Four" (Банды четырех), опубликованная Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. В этой книге сначала обсуждаются возможности и ловушки объектно-ориентированного программирования, а затем рассматриваются классические шаблоны проектирования для системы объектно-ориентированного программирования. Дополнительные сведения об истории шаблонов проектирования можно найти здесь. Типы шаблонов проектирования Шаблоны проектирования можно разделить на 3 категории.
В этой статье я собираюсь обсудить несколько примеров таких шаблонов. Такими шаблонами являются:
Шаблоны создания Шаблон единственного объекта (Singleton) Шаблон Singleton создает класс, для которого на протяжении всего выполнения приложения создается единственный экземпляр объекта, поэтому всякий раз, когда любой другой объект пытается обратиться к объекту этого класса, он всегда обращается именно к этому единственному объекту.
В приведенном выше коде можно видеть, что я специально объявил конструктор как private. Это гарантирует невозможность создания объекта этого класса извне. С другой стороны, при этом нужно создать свойство, которое будет возвращать статический экземпляр объекта, представленное в самом классе. Это предоставит всем внешним сущностям доступ к объекту. Шаблон фабрики (Factory) Шаблон фабрики связан с созданием экземпляра объекта без предоставления логики создания экземпляра. Другими словами, фабрика фактически является создателем объекта с общим интерфейсом.
В приведенном выше коде можно видеть, что я создал один интерфейс, названный IPeople, и реализовал его в двух классах, Villagers и CityPeople. В зависимости от типа, переданного в объект фабрики, я возвращаю исходный конкретный объект как интерфейс IPeople. Метод фабрики (Factory Method) Метод фабрики — это просто расширение класса фабрики (Factory). Он создает объект класса с помощью интерфейсов, но, с другой стороны, он также позволяет подклассу определить, экземпляр какого класса будет создаваться.
Можно видеть, что я использовал GetObject в concreteFactory. Это позволяет легко вызвать в данном классе DoSomething(), чтобы получить IProduct. Разработчик также может написать собственную логику, выполняемую после получения объекта в конкретном методе фабрики. Метод GetObject в интерфейсе Factory сделан абстрактным (abstract). Абстрактная фабрика (Abstract Factory) Абстрактная фабрика — это расширение базового шаблона фабрики (Factory). Он предоставляет интерфейсы Factory для создания семейства связанных классов. Другими словами, здесь я объявляю интерфейсы для фабрик, которые, в свою очередь, будут работать так же, как с фабриками.
Метод фабрики также реализуется с помощью общего интерфейса, каждый из которых возвращает объекты. Шаблон построителя (Builder) Этот шаблон создает объект на основе интерфейса, но также позволяет подклассу определить, экземпляр какого класса будет реализован. Он также обеспечивает более тонкое управление процессом создания. В реализации шаблона построителя используется концепция директора (Director). Директор фактически создает объект, а после этого также выполняет несколько задач.
В случае шаблона построителя можно видеть, что директор фактически использует CreateBuilder для создания экземпляра построителя. Поэтому после фактического создания построителя мы также можем вызвать в нем несколько типовых задач. Шаблон прототипа (Prototype) Этот шаблон создает разновидность объекта, используя его прототип. Другими словами, при создании объекта Prototype класс фактически создает его клон и возвращает его в качестве прототипа.
Как можно видеть, я, когда понадобилось, использовал метод MemberwiseClone для клонирования прототипа. Необходимо помнить, что MemberwiseClone — это фактически только копия. Чтобы сделать копию более глубокой, понадобится вызывать MemberwiseClone рекурсивно для каждого объекта, пока не будут реализованы его значения. Структурные шаблоны Шаблон адаптера (Adapter) Шаблон адаптера преобразует один экземпляр класса в другой интерфейс, ожидаемый клиентом. Другими словами, шаблон адаптера фактически делает два класса совместимыми.
В этой структуре адаптер используется, чтобы сделать класс MyClass2 несовместимым с интерфейсом IAdapter. Шаблон моста (Bridge) Шаблон моста объединяет объекты в древовидную структуру. Он отделяет абстракцию от реализации. Здесь абстракция — это клиент, из которого будут вызываться объекты.
Таким образом, можно видеть, что классы Bridge являются реализацией, использующей ту же ориентированную на интерфейсы архитектуру для создания объектов. С другой стороны, абстракция берет объект из фазы реализации и выполняет его метод. Это позволяет полностью отделить одно от другого. Шаблон декоратора (Decorator) Шаблон декоратора используется для динамического создания ответственностей. Это означает, что в случае использования шаблона декоратора в каждый класс добавляются специальные характеристики. Другими словами, шаблон декоратора — это то же самое, что и наследование.
Это то же самое отношение родителя и потомка, в котором в класс-потомок добавляется новая функция, называемая Method2, а другие характеристики наследуются от родителя. Шаблон составного компонента (Composite) Этот шаблон рассматривает компоненты как соединение одного или нескольких элементов, позволяя отделять компоненты друг от друга. Другими словами, шаблоны составных компонентов — это шаблоны, из которых можно легко выделить отдельные элементы.
В приведенном коде можно видеть, что в in NormalComposite элементы IComposite можно легко отделить. Шаблон маховика (Flyweight) Маховик позволяет совместно использовать объемные данные, общие для всех объектов. Другими словами, если одни и те же данные повторяются для каждого из объектов, можно воспользоваться этим шаблоном, чтобы указать на один объект и, таким образом, легко сэкономить место.
Здесь FlyweightPointer создает статический член Company, используемый для каждого объекта класса MyObject. Шаблон для запоминания состояния (Memento) Шаблон запоминания позволяет захватывать внутреннее состояние объекта, не нарушая инкапсуляцию, и позднее, в случае необходимости, отменять/ откатывать внесенные изменения.
Можно видеть, что объект Memento фактически используется, чтобы откатить (Revert) изменения, внесенные в объект. Шаблоны поведения Шаблон посредника (Mediator) Шаблон посредника гарантирует, что компоненты являются слабосвязанными, то есть они не вызывают друг друга напрямую, всегда используя для решения такой задачи отдельно реализованный объект-посредник.
Приведенный код показывает, как класс Mediator регистрирует все компоненты внутри себя, а затем вызывает свой метод, когда это требуется. Шаблон наблюдателя (Observer) Если несколько объектов связаны некоторыми отношениями, наблюдатель уведомит все зависимые элементы о каких-либо изменениях в родительском элементе. Корпорация Майкрософт уже реализовала этот шаблон как коллекцию ObservableCollection. Я же здесь реализую самый базовый шаблон наблюдателя.
Приведенный код позволяет получить представление о том, что после регистрации для уведомления можно будет получать уведомления при вызове ChangeState. Шаблон итератора (Iterator) Этот шаблон представляет собой способ последовательно доступа к элементам набора. Одним из примеров этого шаблона является интерфейс IEnumerable, предлагаемый корпорацией Майкрософт. Разрешите мне показать данный шаблон на примере этого интерфейса.
В приведенном коде можно видеть, что я реализовал интерфейс IEnumerable, который фактически соответствует блоку итератора. Разработчик также может реализовать этот интерфейс самостоятельно, добавляя несколько методов, таких как First(), Last(), Next() и т. д. Так как эти методы уже реализованы в качестве методов расширения интерфейса IEnumerable, я просто немного упростил его использование. Заключение В этой статье представлены самые основные шаблоны проектирования, используемые чаще всего. Конечно, есть и другие шаблоны проектирования. Я попытаюсь обновить это описание в ближайшем будущем. Не забывайте критиковать меня и присылать замечания, обнаружив в реализации ошибку или что-то интересное. Я наверняка учту их в новой версии этой статьи. Спасибо, что прочитали. Счастливого программирования. Если эта статья понравилась, подпишитесь на наш RSS-канал. Можно также подписаться по электронной почте на наш раздел "Интервью, код и форумы". |
Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.