Top Banner
Gang of four, the book review. Structural patterns
31

Gang of four review.Structural patterns

Dec 05, 2014

Download

Documents

local presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Gang of four review.Structural patterns

Gang of four, the book review.

Structural patterns

Page 2: Gang of four review.Structural patterns

Структура книги

Книга разделена на две основные части. Превая часть (главы 1 и 2) описывает что есть паттерны проектирования и как они помогают решать вопросы проектирования ПО. Так же в ней включены примеры дизайна для наглядности применения паттернов проектирования на практике.

Вторая часть книги (главы 3, 4, 5) - это непосредственно каталог паттернов. Каталог составляет основную часть книги. Все три главы второй части книги соответствуют трем разым типам паттернов, которые авторы разбили на три группы:

● паттерны создания,● структурные паттерны,● паттерны поведения.

Авторы предлогают использовать книгу несколькими разными способами. От начала и до конца прочитать книгу и по очереди выучить все паттерны. Другой же способ заключается в изучении нужных Вам паттерном и, так как книга "усеяна" ссылками с одного паттерна на другой, то таким образом очень легко улавливать связи между паттернами, как они комбинируются и какие из них подходят друг к другу. Ссылки между книгами можно использовать как логический гайд по книге.

Page 3: Gang of four review.Structural patterns

Самой сложной частью дизайна объектно-ориентированных систем - это декомпозиция их на объекты. Эта задача сложна по многим причинам: энкапсуляция, детализация, зависимости, гибкость, производительность, перспективы развития, повторное использование, и т. д. Все это влияет на декомпозицию и зачастую, удовлетворение всех вышеупомянутых причин в дизайне системы, может приводить к конфликтам, например, более гибкая система наверняка будет иметь меньшую производительность.

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

Большинство объектов в дизайне порождается анализом модели. Но часто составление дизайна системы заканчивается на составлении класса, который не имеет предствления в реальном мире. Жесткое моделирование проблем реального мира приводит к тому что система вряд ли сможет решить проблемы "завтрашнего дня". Абстракции, появившиеся в процессе проектирования системы - ключ к гибкой системе.

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

Предмет книги

Page 4: Gang of four review.Structural patterns

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

Тип - это имя, используемое для обозначения определенного интерфейса. Если говорить об объекте типа Окно, значит этот объект должен принимать все запросы, определенные в интерфейсе Окна. Объект может иметь много типов и абсолютно разные объекты могут иметь общие типы. Часть интерфейса объекта может характеризоваться одним типом, а другие части - другими типами. Тип является подтипом другого типа, если его интерфейс содержит подинтерфейс подтипа.

Интерфейсы - основа объектно-ориентированных систем. Объекты общаются только через интерфейсы. Но интерфейсы ничего нам не говорят о реализации.

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

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

Немного теории

Page 5: Gang of four review.Structural patterns

Название паттернаНазвание паттерна кратко передает сущность идеи. Правильно имя важно, так как оно становится частью Вашего словаря паттернов.

НамерениеНебольшая секция, отвечающая на вопрос: что делает данный паттерн? Каковы его обоснования и цель? какой конкретный вопрос дизайна он решает?

Так же известен какАльтернативные названия паттерна.

МотивацияСценарий, описывающий проблему дизайна и как объектная структура паттерна решает проблему.

ПрименениеСитуации в которых применение паттерна наиболее обосновано? Примеры плохого дизайна которые решает паттерн. Методы распознавания таких ситуаций.

СтруктураГрафическое представление классов в рассматриваемом паттерне.

УчастникиКлассы и/или объекты, участвующие в дизайне паттерна и их ответственность.

СотрудничествоВзаимодействие участников для достижения цели.

ПоследствияКомпромиссы и результаты использования шаблона.

ПрименениеТонкости и техники о коих нужно знать при использовании шаблона.

Пример кодаПримеры применения паттерна на C++ или Smalltalk.

Известные проблемыПримеры паттерна, найденные в реальных системах.

Связанные паттерныСвязи между паттернами, различия схожих.

Структура описания паттерна

Page 6: Gang of four review.Structural patterns

Классификация паттернов

Назначение

Создание Структурирование Поведение

Класс ● Factory Method ● Adapter ● Interpreter

● Template Method

Объект ● Abstract Factory

● Builder

● Prototype

● Singleton

● Adapter

● Bridge

● Composite

● Decorator

● Facade

● Proxy

● Chain of Responsibility

● Command

● Iterator

● Mediator

● Memento

● Flyweight

● Observer

● State

● Strategy

● Visitor

Наб

ор п

атт

ерно

в

Page 7: Gang of four review.Structural patterns

ОПРЕДЕЛЕНИЕ

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

Из Wikipedia:"В программировании, паттерн адаптер это один из шаблонов проектирования, который превращает некий интерфейс класса в совместимый интерфейс. Адаптер позволяет классам работать сообща в случаях, когда это невозможно из-за несовместимости интерфейсов, предоставляя клиенту свой интерфейс, в то время как сам по себе он использует оригинальный интерфейс."

Паттерн Adapter

Page 8: Gang of four review.Structural patterns

ПРИМЕР ИЗ ЖИЗНИ

Паттерн Adapter

Улетел на малую Родину

Page 9: Gang of four review.Structural patterns

Пример кода

Паттерн Adapter

/** * Vendor Interface */interface EmailSubsribe{ public function subscribe(email); public function unsubscribe(email); public function sendUpdates();}

/** * Vendor Interface Implementation */class AdidasEmail implements EmailSubsribe{ public function subscribe(email) { /* code */ } public function unsubscribe(email) { /* code */ } public function sendUpdates() { // Получить доступных подписчиков // Получить доступные обновления // Отослать всем всё }}adidasEmailer = new AdidasEmail();adidasEmailer.sendUpdates();

/** * Vendor new Implementation */class AdidasEmailNew{ public function subscribe(email) { /* code */ } public function unsubscribe(email) { /* code */ } public function getSubscribers() { /* code */ } public function sendEmails(subscribers) { // Получить доступные обновления // Отослать всем всё }}adidasEmailer = new AdidasEmailNew();subscribers = adidasEmailer.getSubscribers();adidasEmailer.sendEmails(subscribers);

Page 10: Gang of four review.Structural patterns

Паттерн AdapterСогласно предыдущему коду - послевыхода новой версии класса, измениласьего сигнатура и нарушилась обратная совместимость с предыдущей версиейкласса.

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

/** * Vendor new Implementation */class AdidasEmailAdapter implements EmailSubscribe{ public function subscribe(email) { /* code */ } public function unsubscribe(email) { /* code */ } public function sendUpdates() { adidasEmailer = new AdidasEmailNew(); subscribers = adidasEmailer.getSubscribers(); adidasEmailer.sendEmails(subscribers); }}adidasEmailerAdapter = new AdidasEmailAdapter();adidasEmailerAdapter.sendUpdates();

Page 11: Gang of four review.Structural patterns

ОПРЕДЕЛЕНИЕ

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

Паттерн проектирования Bridge производит декомпозицию абстракции от ее реализации так, что бы они могли существовать независимо друг от друга.

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

Bridge паттерн полезен когда класс и то что он делает зачастую варьируются. Сам по себе класс может быть представлен как реализация, а то что он делает - абстракция. Этот паттерн можно так же представить как двухуровневая абстракция.

Паттерн Bridge

Page 12: Gang of four review.Structural patterns

КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА BRIDGE

● Абстракция○ определяет интерфейс абстракции○ содержит ссылку на объект типа Исполнитель

● Модернизированная Абстракция○ расширяет интерфейс, определенный абстракцией

● Исполнитель○ определяет интерфейс для классов-сателитов

● Конкретный Исполнитель○ реализация Исполнителя

Паттерн Bridge

Page 13: Gang of four review.Structural patterns

Паттерн BridgeКЛАССИЧЕСКИЙ

С ПОМОЩЬЮ BRIDGE

Окно

Linux-Окно Mac-Окно Окно-с-иконкой

Mac-Окно-с-иконкойLinux-Окно-с-иконкой

Окно

Mac-ОкноLinux-Окно

Иконки

Для MacДля Linux

Page 14: Gang of four review.Structural patterns

Паттерн Bridge

отдел

сиcтем

Депозитный калькулятор для ПриватБанка

Депозитный калькулятор дляА-Банка

ПРИМЕР ИЗ ЖИЗНИ

Page 15: Gang of four review.Structural patterns

Пример кода

Паттерн Bridge

/** "Implementor" */interface DrawingAPI { public void drawCircle(double x, double y, double radius);} /** "ConcreteImplementor" 1/2 */class DrawingAPI1 implements DrawingAPI { public void drawCircle(double x, double y, double radius) { System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius); }} /** "ConcreteImplementor" 2/2 */class DrawingAPI2 implements DrawingAPI { public void drawCircle(double x, double y, double radius) { System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius); }} /** "Abstraction" */abstract class Shape { protected DrawingAPI drawingAPI; protected Shape(DrawingAPI drawingAPI){ this.drawingAPI = drawingAPI; } public abstract void draw(); public abstract void resizeByPercentage(double pct);}

/** "Refined Abstraction" */class CircleShape extends Shape { private double x, y, radius; public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) { super(drawingAPI); this.x = x; this.y = y; this.radius = radius; } // low-level i.e. Implementation specific public void draw() { drawingAPI.drawCircle(x, y, radius); } // high-level i.e. Abstraction specific public void resizeByPercentage(double pct) { radius *= pct; }} /** "Client" */class BridgePattern { public static void main(String[] args) { Shape[] shapes = new Shape[] { new CircleShape(1, 2, 3, new DrawingAPI1()), new CircleShape(5, 7, 11, new DrawingAPI2()), }; for (Shape shape : shapes) { shape.resizeByPercentage(2.5); shape.draw(); } }}

Page 16: Gang of four review.Structural patterns

ОПРЕДЕЛЕНИЕ

Паттерн Composite собирает объекты в структуру бинарного дерева для представления иерархической структуры. Он так же позволяет клиенту обращаться с отдельными объектами и композициями объектов в одном формате.

В иерархических структурах код для работы с контейнерами и примитивами зачастую отличается, даже если, в основном, обращения одинаковы. Разделив эти объекты, приложение усложняется. Паттерн Composite описывает как использовать рекурсивную композицию, что бы для клиентов не было отличия между контейнерами и примитивами. Пример: графический редактор.

Ключевым игроком Паттерна композит является абстрактный класс, который представляет как контейнер, так и примитив.

Паттерн Composite

Page 17: Gang of four review.Structural patterns

КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА COMPOSITE

● Компонент○ определяет интерфейс для объектов композиции○ реализует стандартное поведение для интерфейса, общего для всех

классов○ определяет интерфейс для доступа и управления дочерними листками○ [не обязательно] определяет интерфейс для рекурсивного доступа к

родителям в Композиции

● Листок○ представляет объекты Листков в Композиции. Листок не имеет

наследников○ определяет поведение примитивов в Композиции

● Композиция○ определяет поведение для компонентов, имеющих наследников○ имеет наследников○ реализует методы дочерних элементов через интерфейс Компоненты

● Клиент○ управляет объектами Композиции через интерфейс Компоненты

Паттерн Composite

Page 18: Gang of four review.Structural patterns

Паттерн Composite

КЛАССИЧЕСКИ

layer = new Layer;layer.elements = [ new Parallelogram(pParams), new Ellipse(eParams), new Triangle(tParams)];layer.drawLayer();each (layer.elements as element) element.drawElement();

слой(композиция)

прим

итив

ы(л

истк

и)

С ПОМОЩЬЮ COMPOSITE

layer = new Layer;layer.elements = [ new Parallelogram(pParams), new Ellipse(eParams), new Triangle(tParams)];layer.draw();

Page 19: Gang of four review.Structural patterns

Пример кода

Паттерн Composite

/** "Component" */interface Graphic{ public void print();} /** "Composite" */import java.util.List;import java.util.ArrayList;class CompositeGraphic implements Graphic{ private List<Graphic> childGraphics = new ArrayList<Graphic>();

public void print() { for (Graphic graphic : childGraphics) { graphic.print(); } } public void add(Graphic graphic) { childGraphics.add(graphic); } public void remove(Graphic graphic) { childGraphics.remove(graphic); }}

/** "Leaf" */class Ellipse implements Graphic{ public void print() { System.out.println("Ellipse"); }} /** Client */public class Program{ public static void main(String[] args) { Ellipse ellipse1 = new Ellipse(); Ellipse ellipse2 = new Ellipse(); Ellipse ellipse3 = new Ellipse(); Ellipse ellipse4 = new Ellipse(); CompositeGraphic graphic = new CompositeGraphic(); CompositeGraphic graphic1 = new CompositeGraphic(); CompositeGraphic graphic2 = new CompositeGraphic(); graphic1.add(ellipse1); graphic1.add(ellipse2); graphic1.add(ellipse3); graphic2.add(ellipse4); graphic.add(graphic1); graphic.add(graphic2); graphic.print(); }}

Page 20: Gang of four review.Structural patterns

ОПРЕДЕЛЕНИЕ

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

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

Паттерн Decorator

Page 21: Gang of four review.Structural patterns

КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА DECORATOR

● Компонент○ определяет интерфейс для объектов, которые смогут динамически

добавлять функциональность

● Конкретный компонент○ определяет объект, которому можно добавлять функционал

● Декоратор○ определяет интерфейс для объектов которые смогут добавлять себе

функционал динамически○ хранит ссылку на объект-Компонент и определяет интерфейс, который

соответствует интерфейсу Компонента

● Конкретный Декоратор○ добавляет функционао Компоненту

Паттерн Decorator

Page 22: Gang of four review.Structural patterns

Паттерн DecoratorНА ПРИМЕРЕ ФОТОШОПЫ

Page 23: Gang of four review.Structural patterns

Паттерн DecoratorИЛИ БЕЗ ФОТОШОПЫ

Page 24: Gang of four review.Structural patterns

Пример кода

Паттерн Composite

abstract class Window{ public abstract void draw();}

class SimpleWindow extends Window { public void draw() { /*code*/ }}

abstract class WindowDecorator extends Window { protected Window decoratedWindow; public WindowDecorator (Window decoratedWindow) { this.decoratedWindow = decoratedWindow; }

public void draw() { decoratedWindow.draw(); }}

class VerticalScrollBarDecorator extends WindowDecorator { public VerticalScrollBarDecorator (Window decoratedWindow) { super(decoratedWindow); }

@Override public void draw() { super.draw(); drawVerticalScrollBar(); } private void drawVerticalScrollBar() { /*code*/ }}

class HorizontalScrollBarDecorator extends WindowDecorator { public HorizontalScrollBarDecorator (Window decoratedWindow) { super(decoratedWindow); } @Override public void draw() { super.draw(); drawHorizontalScrollBar(); } private void drawHorizontalScrollBar() { /*code*/ }}

public class DecoratedWindowTest{ public static void main(String[] args) { Window decoratedWindow = new HorizontalScrollBarDecorator ( new VerticalScrollBarDecorator(new SimpleWindow()));

}}

Page 25: Gang of four review.Structural patterns

ОПРЕДЕЛЕНИЕ

Паттерн проектирования Facade - позволяет скрыть сложность системы путем сведения всех возможных вызовов к одному объекту, делегирующему их соответствующим объектам системы. Реализация компонентов подситемы закрыта и не видна внешним компонентам. Дизайн Facade-объекта защищает его от изменений в реализации подсистемы.

Паттерн Facade

Page 26: Gang of four review.Structural patterns

КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА FACADE

● Фасад○ знает какие части подсистемы ответственны за выполнения запроса○ делегирует клиентские запросы соответствующим подсистемам

● Подситемы○ выполняет функциональность подситемы○ выполняет работу, делегируеммую объектом Facade○ не имеет представления о Facade, не имеет на него ссылок

Паттерн Facade

Page 27: Gang of four review.Structural patterns

ПРИМЕР ИЗ ЖИЗНИ

Паттерн Facade

Хочу стать частным предпринимателем

НалоговаяПенсионный

фонд

Другие службы**

Банк

Единое окно*

?Куда податься ?

* - вопрос почему оно Единое и не единое на самом деле меня тоже гложжет** - санстанция, лицензирование, пожарная безопастность и т. п.

Page 28: Gang of four review.Structural patterns

ОПРЕДЕЛЕНИЕ

Паттерн проектирования Proxy - предоставляет объект, который контролирует доступ к другому объекту, перехватывая все его вызовы (выполняет функции контейнера).

Существуют следующие разновидности паттерна:● Протоколирующий прокси● Удаленнй заместитель● Виртуальный заместитель● Копировать-при-записи● Защищающий заместитель● Кеширующий прокси● Экранирующий прокси● Синхронизирующий прокси● Smart reference прокси

Паттерн Proxy

Page 29: Gang of four review.Structural patterns

КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА FACADE

● Субъект○ интерфейс, определяющий поведение Реального субъекта

● Реальный субъект○ реализует тип субъекта

● Proxy (Заместитель)○ реализует тип субъекта○ дает возможность добавлять поведение в проксируемый объект

Паттерн Proxy

Page 30: Gang of four review.Structural patterns

ПРИМЕР ИЗ ЖИЗНИ

FirewallProxy

Паттерн Proxy

Бизнеса банка

Топ менеджеры

Другие клиенты

CacheProxy з е р г и

Page 31: Gang of four review.Structural patterns

Пример кода

Паттерн Proxy

interface IMath{ function Add($x, $y); function Sub($x, $y); function Mul($x, $y); function Div($x, $y);} class Math implements IMath{ public function Add($x, $y){return $x + $y;} public function Sub($x, $y){return $x - $y;} public function Mul($x, $y){return $x * $y;} public function Div($x, $y){return $x / $y;}}

class MathProxy implements IMath { protected $math; public function __construct() { $this->math = null; } public function Add($x, $y) { return $x + $y; } public function Sub($x, $y) { return $x - $y; } public function Mul($x, $y) { if ($this->math == null) $this->math = new Math(); return $this->math->Mul($x, $y); } public function Div($x, $y) { if ($this->math == null) $this->math = new Math(); return $this->math->Div($x, $y); }}

$p = new MathProxy; print("4 + 2 = ".$p->Add(4, 2)); print("4 - 2 = ".$p->Sub(4, 2)); print("4 * 2 = ".$p->Mul(4, 2)); print("4 / 2 = ".$p->Div(4, 2));