![]() |
Модераторы: LSD, AntonSaburov |
![]() ![]() ![]() |
|
batigoal |
|
||||||||||||||||||||||||||||||||||||||
![]() Нелетучий Мыш ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6423 Регистрация: 28.12.2004 Где: Санктъ-Петербургъ Репутация: 24 Всего: 151 |
Simple Factory
Служит для создания объектов различных классов на основании информации, переданной во время выполнения программы. Обычно эти классы наследуют от базового класса или интерфейса, т.е. обладают похожей функциональностью. Пример В данном случае Фабрика производит объект Filter1 или Filter2 в зависимости от значения переданного в метод getFilter. Java
C#
Паттерн очень простой, потому и не включен в классические 23 паттерна. Преимущества Позволяет избавиться от хардкодинга. Например, без этого паттерна нам пришлось бы писать
Теперь представим что мы решили дать классам Filter<> более осмысленные имена. Нам пришлось бы прочесывать весь код и менять не один раз. С данным паттерном все просто, достаточно изменить класс SimpleFactory. Паттерн добавляет слой абстракции, отделяя процесс создания объекта от его использования. Фабрика может применять более сложную логику создания объектов; например может создавать их через рефлекшн. Factory Используется, когда неизвестно, объект какого класса нужно будет создать. В отличие от SimpleFactory в Factory отсутствует явный код выбора класса (как в методе getFilter() в предыдущем случае). Этот выбор может осуществляться через полиморфизм. Пример Есть несколько классов Filter<>, наследующих от абстрактного Filter. Каждый из фильтров использует свои ImageFilter (и, вероятно еще к-л компоненты). Java
C#
Суть паттерна в том, что обязанность выбора класса ImageFilter ложится на плечи сабклассов. Тем не менее точка доступа к ImageFilter одна - метод getImageFilter() базового класса. Преимущества. Фактически, те же, что и у SimpleFactory. Логика получения объектов (ImageFilter) отделена от основного кода. Abstract Factory Несмотря на название, использовать абстрактный класс в этом паттерне необязательно. Самое главное отличие его от Factory в том, что один класс предоставляет интерфейс для доступа к группе объектов, а не одному объекту. Пример Мы пишем игру. Есть класс Level, от которого наследуют Level1, Level2 и т п. а каждом уровне - свои монстры двух типов - "слабый" и "сильный". Будем считать что все классы <..>Monster наследуют от некого класса Monster. Java
C#
Здесь класс Level и является Абстрактной Фабрикой, т.к. дает доступ к группе объектов (weakMonster, strongMonster). Теперь можно писать такой код:
Таким образом, основной код понятия не имеет, каких монстров он использует. Преимущества. Использование Abstract Factory, как и Factory, позволяет писать код, который "не знает" какие конкретно объекты он использует. Наследование позволяет сабклассам самим создавать об3екты, которые им нужны; полиморфизм дает возможность использовать их. Это упрощает как написание, так и поддержку кода, делает его более робастным. Singleton "Одиночка". Паттерн проименяется в случае, когда важно, чтобы в данный момент времени существовал один единственный объект какого-либо класса. Зачем это нужно? Предположим мы написали простую базу данных. Наше АПИ включает в себя класс LockManager. Объект этого класса занимается тем, что предотвращает одновременный доступ клиентов к одному и тому же ряду в БД, то есть пока один клиент меняет запись (вызывает метод, передающий изменения), менеджер не позволяет никому другому эту запись изменить. Некий другой программер решил воспользоваться этим АПИ, и создал 2 объекта LockManager. Теперь возможна ситуация, когда 2 клиента попытаются одновременно менять одну запись. Что может привести к нехорошим последствиям. Естественно, нужно сделать так, чтобы можно было создать только 1 объект класса LockManager, а при попытке создать большее количество объектов, дать знать программеру об ошибке. В целом подход один: делаем приватный конструктор, храним инстанс синглтона в самом классе как статик поле; получаем его статик методом типа getInstance(). Есть несколько способов реализации Синглтона. 1. В getInstance() проверяем, если ссылка не нул, возвращаем нул. 2. Если ссылка не нул, кидаем иксепшн. Пример реализации 1. Java
Код на шарпе не привожу, т.к. он на 99% такой же. Вариант с иксепшном аналогичен; в строчке else return null; вместо ретурна нужно бросать иксепшн. Оба метода имеют свои преимущества и недостатки, но они настолько тонкие, что нет смысла о них здесь говорить. Преимущества. Дает полный контроль над количеством созданных объектов класса. Паттерн легко применить дкля случая когда нужно чтобы можно было создать не более N объектов; или точно N объектов. Builder Как следует из названия, паттерн собирает ряд объектов в одно целое, "строит" нечто новое. Сравним паттерн с Factory: Factory: вы делаете заказ на определенную машину, фабрика ее производит. Builder: вы даете строителю нужные материалы. Тот что-то из них делает. Этот паттерн часто используется для построения ГУИ. Например, мы читаем данные из БД, причем для удобства сортировки выносим один столбец со всеми возможными должностями работников отдельно, в виде JList или JComboBox (ListBox, ComboBox). Лист удобен тогда, когда элементов в списке мало, комбобокс - когда их много. Можно легко решить проблему следующим псевдокодом:
Другим решением было бы создать два класса - строителя, каждый был бы ответственен за построение определенного ГУИ. В приведенном выше случае создание двух классов було бы слишком; но если бы мы решили создать 2 ОЧЕНЬ разных ГУИ, то 2 Билдера было бы решением более "чистым". Совсем необязательно чтобы Строитель строил визуальные компоненты. Пример Это очень надуманный пример, поясняющий тем не менее суть паттерна. В роли Builderов выступают ArrayListCollection и ArrayCollection. Каждый создает свой тип коллекции. Для выбора Билдера используется паттерн SimpleFactory (метод GetMyCollection) C#
Преимущества. Билдер отделяет логику создания сложных компонентов от кода, использующего эти компоненты. Предположим мы на основе паттерна SimpleFactory выбираем Builder, который строит ГУИ для некого визуального компонента. Такой код легче поддерживать (ГУИ для каждого случая создается в своем классе/методе); легче реюзать; легче дополнять (например, третьим вариантом ГУИ) Adapter Adapter преобразует ("адаптирует") один интерфейс в другой интерфейс. Может существовать множество причин для такого преобразования, например: 1. Класс А имеет сложный интерфейс, скорее "низкоуровневый". Для многих операций приходится делать несколько вызовов методов этого класса. Имеет смысл переработать этот интерфейс в более простой. 2. Интерфейс класса А очень широк; но для определенных операций нам нужен более узкий, или специализированный интерфейс. Например, один и тот же класс может использоваься клиентами (удаленно), но может также быть использован администратором сервера. В таком объект не должен "показывать" клиентам всю функциональность. Есть 2 основных варианта реализации Адаптера: через наследование и через композицию. Примеры Java Через наследование. Мы написали класс BinaryWriter, который работает с бинарными файлами, при этом шифруя информацию нашим собственным алгоритмом. Но нам часто приходится писать текстовые данные. Применение Адаптера упрощает работу.
Теперь мы можем вместо вызовов нескольких методов класса BinaryWriter использовать append. Но класс BinaryStringWriter по-прежнему обладает всеми паблик методами класса BinaryWriter! Это пример так называемого Two-Way Adapter - двустороннего адаптера, который может выступать как BinaryStringWriter, так и BinaryWriter. Через композицию. Класс Account предоставляет интерфейс для управления аккаунтом клиента - снятием денег, удалением аккаунта и пр. Но показывать клиенту определенную функциональност, например метод deleteAccount, не слишком удачный вариант. Поэтому мы конструируем адаптер - класс ClientAccount, который содержит Account как приватное поле. Класс ClientAccount предоставляет клиенту лишь часть интерфейса этого поля.
Преимущества Адаптер - это что-то вроде "переходника" - он позволяет рассматривать один интерфейс по-разному. Например, можно изменить интерфейс класса JTree, сделав его похожим на интерфейс класса ArrayList или HashMap. Можно переделать интерфейс нескольких совершенно различных классов так, что он будет одним и тем же; такие адаптеры называются Plaggable Adapters. Если подумать, это очень интересная концепция. Bridge Адаптер преобразует интерфейс объекта, оставляя объект "нетронутым". Например, часы в наше время можно засунуть куда угодно, скажем в авторучку или чайник. Но часы останутся по сути своей часами; поменяется их вид и количество кнопочек, и только. Bridge (мост) делает прямо противоположное - он "фиксирует" интерфейс объекта. Хороший пример Моста - электрическая розетка. Все что нас волнует - это как в нее засунуть вилку и какое там напряжение; сама же электроэнергия может идти с ТЭЦ, ГЭС, АЭС, солнечноей батареи или ветряка - нам все равно. И если завтра вместо ветряка будут пользовать солнечную батарею или белку в колесе, мы этого не заметим. Часто Мост реализован как связка интерфейс-конкретный класс. Пример C# Объект класса Calculator производит некие вычисления в методе Calculate. По завершении метода он вызывает соответствыющие методы всех зарегистрированных слушателей. Слушатели в свою очередь наследуют от интерфейса IBridge и таким образом гарантированно обладают методом DoCalculationFinished. Перед вычислением клиентское приложение регистрирует класс слушателя и его метод DoCalculationFinished будет вызван при появлении события CalculationFinished. Таким образом, работа клиента основана на наличии класса с интерфейсом IBridge, больше его ничто не интересует. Как показывает пример, сам Мост может делать далее с данными что угодно - слать по сети или сохранять на диск.
Преимущества Паттерн сохраняет интерфейс клиента, сохраняя тем самым труд и время программера. Легко добавить нужную функциональность - например, можно добавить класс PrintBridge, который будет печатать результат, TransmitBridge, который отфильтрует данные и передаст их для дальнейших вычислений, и т п. Composite Обычно мы работаем либо с индивидуальными объектами, либо с коллекциями. Паттерн Composite объединяет оба случая. Пример композита - дерево. Дерево имеет листья (листья не могут иметь детей) и ноды, который могут содержать другие ноды или листья. Суть паттерна в том, чтобы и ноды, и листья имели один интерфейс. Пример Java Предположим, что приложение описывает некую иерархическую структуру, например, сотрудников фирмы. Любой сотрудник будет описываться классом, наследующим от AbstractEmployee, т.е. интерфейс у всех классов будет один. AbstractEmployee по сути есть часть древовидной структуры, и хранит ссылку на родителя и детей. Сабклассы AbstractEmployee по-своему имплементруют соответствующие методы; так например класс Employee (обычный сотрудник) на дереве будет листом, т.е. getSubordinates должен возвращать null.
Преимущества Этот паттерн широко используется в Java и C#. Например, любая JPanel (Panel) содержит ссылки на свои компоненты (которые в свою очередь сами держат ссылки на их компоненты). Поскольку компоненты наследуют от Component (Control) то и интерфейс у них один. Композит позволяет упростить работу с похожими объектами. Decorator Декоратор похож на Адаптер в том смысле, что он преобразует интерфейс исходного класса. Однако, как и в случае с многими паттернами, цель Декоратора другая. Его задача - изменить интерфейс нескольких классов. Адаптер удобно использовать, делая его сабклассом нужного класса. А если нужно 20 классов "привести" к одному интерфейсу? Нужно создавать 20 сабклассов. Другой момент - Декоратор часто используется в ГУИ. Суть паттерна в том, что создается класс, содержащий поле; класс этого поля является суперклассом (или интерфейсом) для тех классов, которые нам нужно "продекорировать". Пример Java Данный пример декорирует JPanel - когда указатель мыши находится над панелью, она обводится красной рамкой. В Декоратор мы помещаем не JPanel а JComponent; поэтому его можно использовать для декорации не только панели.
Преимущества Один Декоратор может менять интерфейс для любого количества компонентов. Facade Что (отчасти) неудобно в ООП и при использовании паттернов - большое количество классов. Чем больше классов - тем сложнее работать. Фасад - это класс, который предоставляет простой интерфейс для работы, и прячет таким образом сложную бизнес логику приложения. Естественно, упрощение интерфейса приводит к потере гибкости при работе с Фасадом. Тем не менее, программист по-прежнему имеет доступ к "низкоуровневому" АПИ. Фасад - всего лишь класс, который упрощает жизнь в некоторых (или многих) случаях. Можно использовать несколько Фасадов, наследующх от одного класса. Пример Чтоб не писать чего-то сложного и нудного, все будет предельно схематично. Есть классы A, B, C. Каждый раз нам приходится визывать ряд методов этих классов:
Создадим класс Facade, в который вынесем Блок 1 и Блок 2 :
Теперь все упрощается
Преимущества Упрощает интерфейс. Клиенту теперь не нужно знать тонкостей работы с A, B и C. ВСе взаимодействие с кэтими классами ограничено двумя методами. С другой стороны, если придется поменять логику взаимодействия этих классов, вероятно, придется менять Фасад, или снова пользоваться исходными методами. Flyweight Объектно-ориентированный подход подразумевает создание классов, и естественно, объектов этих классов. Иногда нужно создать множество объектов одного класса. Если объекты отличаются только несколькими параметрами, применяется паттерн Flyweight. Рассмотрим классический пример - папки на диске. У каждой папки свое название и иконка. Естественно, создавать свой объект для каждой папки - значит зодать множество почти одинаковых объектов.& -------------------- "Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли) ЖоржЖЖ |
||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||
![]() ![]() ![]() |
Правила форума "Java" | |
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |