К списку форумов К списку тем
Регистрация    Правила    Главная форума    Поиск   
Имя: Пароль:
Рекомендовать в новости

Паттерны проектирования

Гость
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
Цитата:
Сообщение от Философ Посмотреть сообщение
11-КоРоЛь &gt; прекращай такие простыни постить.
Что не так и почему на ты?
Гость
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
слабовато как-то..


К списку вопросов






Copyright ©, Все права защищены