0
- 12.09.2012 - 09:21
|
Уважаемые разработчики. Как вы применяете в своих проектах шаблоны легендарной банды четырех (декоратор, адаптер, шаблонный метод и т.д.)? Есть ли в Краснодаре программисты (или команды), умеющие общаться на бронебойном языке паттернов? Возможны ли тематические встречи для обмена опытом? | |
1
- 12.09.2012 - 10:19
|
Паттерн Абстрактная фабрика http://ru.wikipedia.org/wiki/%D0%90%...BD%D0%B8%D1%8F) Начнем обсуждение с рассмотрения простого примера. Допустим есть некий веб-система документооборота и в нем мы реализуем 2 разных интерфейса для управления различными типами пользователей (физ и юр лица, коротко юрик и физик). У каждого типа пользователя есть общие и уникальные атрибуты (сначала идут общие). Физик: ID, телефон, email,ФИО, номер паспорта, ОГРНИП Юрик: ID, телефон, email, название организации, ОГРН Допустим этот набор полей хранится в базе и он всегда нам доступен через операцию $db::get_fields($type) где $type = 0 юрик, 1 физик. В каждом веб-интерфейсе должен быть фильтр и таблица. Операции фильтрации, сортировки, создания, редактирования, удаления полностью идентичны для обоих типов. Вот здесь и применяется шаблон абстрактная фабрика. Схематично я изобразил его так: А теперь код: <?php interface UserFactory ** public function get_filter_data(); public function get_table_data(); ** class LegalFactory implements UserFactory ** public function get_filter_data() ** return (new LegalFilter()); ** public function get_table_data() ** return (new LegalTable()); ** ** class NaturalFactory implements UserFactory ** public function get_filter_data() ** return (new NaturalFilter()); ** public function get_table_data() ** return (new NaturalTable()); ** ** abstract class UserFilter ** // возвращает данные, которые уже дльше передаем в представление filter.tpl public function get_data(); ** class LegalFilter extends UserFilter ** ** class NaturalFilter extends UserFilter ** ** abstract class UserTable ** // возвращает данные, которые уже дльше передаем в представление table.tpl public function get_data(); ** class LegalTable extends UserTable ** ** class NaturalTable extends UserTable ** ** class Client ** private $factory; public function legal_builder() ** $this->factory = new LegalFactory(); ** public function natural_builder() ** $this->factory = new NaturalFactory(); ** public function out() ** echo $this->factory->get_filter_data(); echo $this->factory->get_table_data(); ** ** $client = new Client(); $client->legal_builder(); $client->out(); | |
2
- 12.09.2012 - 10:21
|
В коде забыл дописать использование $db::get_fields($type) но я думаю, вы и сами без проблем допишите | |
3
- 12.09.2012 - 10:27
|
Чего мы добились? Мы инкапсулировали наиболее часто изменяемую логику: изменение типов лиц (например, добавление 3-го ИП), изменение полей для каждого тип. При этом код клиента остается неизменным очень долгое время. У этого паттерна есть родственный - фабричный метод. Он отличается тем, что за создание объекта отвечает абстрактный родительский метод, который переопределяется в подклассах. | |
4
- 12.09.2012 - 10:46
| Код плохо вставился. Вместо ** должно быть ** | |
5
- 12.09.2012 - 10:47
| т.е. открывающая фигурная скобка | |
6
- 12.09.2012 - 13:18
| Ничего, мы привыкли к людям, которые кроме классов и MVC ничего не знают. | |
7
- 12.09.2012 - 14:40
|
В далеком 2005-м году видел проект, нашпигованный паттернами по самое нехочу. Работал крайне медленно. Поддерживать его было вообще мрак. Правда, это был еще .NET 1.1, но с тех пор отношение к паттернам у меня осторожное. | |
8
- 12.09.2012 - 22:35
| Это что такое было? :) | |
9
- 14.09.2012 - 10:28
|
7-CPU > Чтобы паттерны не превратились в плохое решение, не нужно слепо следовать им. Еще есть рефакторинг и код ревью. | |
10
- 14.09.2012 - 10:53
|
0-КоРоЛь > Весьма активно использую. Наиболее полезен "Шаблонный метод", на втором месте "Фасад", тройку лидеров замыкает Синглтон. | |
11
- 14.09.2012 - 11:11
|
Паттерн Стратегия. http://ru.wikipedia.org/wiki/%D0%A1%...BD%D0%B8%D1%8F) Разрабатываем веб-систему, состоящую из набора интерфейсов. Каждый интерфейс состоит из фильтра и таблицы. Поля в фильтре задаются программно. Т.е. какие поля будут выводиться в конкретном фильтре — мы заранее не знаем. У нас есть следующие типы полей: текст (имеется ввиду текстовое поле ввода) селект чекбокс (имеется ввиду один квадратик) радиокнопки (имеется ввиду несколько кружочков) Чтобы вывести поле, нам нужно знать данные: name — имя латинскими буквами, используется для идентификации поля в форме (атрибут name у инпута) caption — русскоязычное название value — текущее значение value_list — список предопределенных значений поля. Эти данные нужны только для селекта и радиокнопки Простой метод решения — сделать общего предка Field и все операции запихнуть в него - изображен на следующей схеме: Получается, что у текста и чекбокса тоже может быть список значений — но это неправильно. Правильное решение. Выделить типы поведения полей. В данном случае у нас может быть 2 поведения: TextBehavior и SelectBehavior. При этом класс field будет делегировать процедуру получения значений другому объекту. Как это будет выглядеть: Получается, что при создании поля клиент должен установить поведение этому полю. В классе SelectBehavior мы расписываем процедуру получения списка значений. В классе TextBehavior мы оставляем пустую реализацию метода get_value_list Теперь сам код: <?php // общий класс class Field ** protected $name; protected $caption; protected $value; protected $behavior; public function __construct(Behavior $behavior) ** $this->set_behavior($behavior); ** public function set_behavior($behavior) ** $this->behavior = $behavior; ** public function get_value_list() ** return $this->behavior->get_value_list(); ** ** class Text extends Field ** // тут пишем специфичный код для поля ** class Select extends Field ** // тут пишем специфичный код для поля ** class Checkbox extends Field ** // тут пишем специфичный код для поля ** class Radio extends Field ** // тут пишем специфичный код для поля ** interface Behavior ** public function get_value_list(); ** class SelectBehavior ** public function get_value_list() ** // берем список значений из базы $value_list = array('a', 'b', 'c'); return $value_list; ** ** class TextBehavior ** public function get_value_list() ** ** ** /** * Код клиента теперь можно писать таким образом */ $text_behavior = new TextBehavior(); $select_behavior = new SelectBehavior(); $text = new Text($text_behavior); $checkbox = new Checkbox($text_behavior); $select = new Select($select_behavior); $radio = new Radio($select_behavior); /** * дальше идет вывод полей например так echo $text->display(); * или передача шаблонизатору */ | |
12
- 14.09.2012 - 11:17
|
Стратегия - уникальный паттерн, который можно использовать где угодно. Задача этого паттерна - инкапсулировать сложные алгоритмы. Еще стратегия является частью реализации паттерна MVC. Если представления представить как общий класс представления и представление каждого интерфейса. Поведение представления инкапсулируется в контроллерах, которые так же разбиваются на общий класс контроллера и контроллер для каждого интерфейса. Так же, этот паттерн показывает наглядные преимущества композиции перед наследованием. | |
13
- 14.09.2012 - 11:20
|
10-Философ > Синглтон в вебе должен быть на первом месте ) В каких контекстах (предметных областях) обычно используете фасад? | |
14
- 14.09.2012 - 11:25
|
Еще стратегия незаменимый паттерн в программировании игрушек. Когда разных персонажей могут быть разные виды оружия. | |
15
- 14.09.2012 - 11:30
|
11-КоРоЛь > прекращай такие простыни постить. 13-КоРоЛь > фасад - по прямому назначению (например, веб-сервис объединяет тучу мелких компонентов в одну подсистему) >Синглтон в вебе должен быть на первом месте ) до самого веба я так и не добрался (пока не добрался) | |
16
- 14.09.2012 - 11:35
|
Из разговора двух программистов, использующих паттерны: - Буду делать древовидную структуру объектов с помощью компоновщика, обходить ее можно будет визиторами без особых потерь быстродействия. - А я сделаю фасад, чтобы предоставить интерфейс для управления твоими объектами. - Постой, но у нас в коде есть старые объекты, которые нельзя будет изменить под новую структуру. - Точно.. тогда для них мы будем использовать декораторы. - Согласен, это будет идеальное решение! | |
17
- 14.09.2012 - 11:40
| Что не так и почему на ты? | |
18
- 14.09.2012 - 11:43
|
16-КоРоЛь > Если коту делать нечего, он яйца лижет. Программисту делать нечего - ищет куда-бы ещё прилепить паттерн. Если ничего хорошего придумать не удалось, по умолчанию используется Визитор - поубивал бы! | |
19
- 14.09.2012 - 12:11
|
18-Философ > прошу использовать свои высказывания в чуть более вежливой форме, ок? Или если это крик души, не направляйте его в мою сторону. Если грамотно использовать визитор, это очень мощный паттерн. Через него можно создавать/удалять/сортировать/перемещать/находить ветки/листья дерева. По большому все эти алгоритмы можно использовать в самом компоновщике, но если используются неоднородные типы узлов в дереве, получается дублирование, которое визитор успешно убирает. Правда его серьезный минус в том, что он "знает" код компоновщика. Про визитор есть любопытная статья на хабре (про upcast visitor можно не читать) http://habrahabr.ru/post/133183/ | |
20
- 14.09.2012 - 18:07
|
19-КоРоЛь > отвратительная статья! Аффтар с самого начала демонстрирует незнание методик OOD: без выделения семантики объектов сразу начинает с диаграммы классов. Есстественно, что с самых первых строк нарушение SRP... в мусор! | |
21
- 19.09.2012 - 08:39
| слабовато как-то.. | |
| Интернет-форум Краснодарского края и Краснодара |