SlideShare a Scribd company logo
1 of 31
Download to read offline
Gang of four, the book
       review.
 Structural patterns
Структура книги
Книга разделена на две основные части. Превая часть (главы 1 и 2) описывает что есть
паттерны проектирования и как они помогают решать вопросы проектирования ПО. Так же
в ней включены примеры дизайна для наглядности применения паттернов проектирования
на практике.

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

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

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

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

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

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

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

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

Основываясь на вышесказанном, паттерны проектирования помогают Вам определить
ключевые елементы в объявлении интерфейсов, а так же исключать не нужные элементы.
Структура описания паттерна
Название паттерна
     Название паттерна кратко передает сущность идеи. Правильно имя важно, так как оно становится частью Вашего
     словаря паттернов.
Намерение
     Небольшая секция, отвечающая на вопрос: что делает данный паттерн? Каковы его обоснования и цель? какой
     конкретный вопрос дизайна он решает?
Так же известен как
     Альтернативные названия паттерна.
Мотивация
     Сценарий, описывающий проблему дизайна и как объектная структура паттерна решает проблему.
Применение
     Ситуации в которых применение паттерна наиболее обосновано? Примеры плохого дизайна которые решает паттерн.
     Методы распознавания таких ситуаций.
Структура
     Графическое представление классов в рассматриваемом паттерне.
Участники
     Классы и/или объекты, участвующие в дизайне паттерна и их ответственность.
Сотрудничество
     Взаимодействие участников для достижения цели.
Последствия
     Компромиссы и результаты использования шаблона.
Применение
     Тонкости и техники о коих нужно знать при использовании шаблона.
Пример кода
     Примеры применения паттерна на C++ или Smalltalk.
Известные проблемы
     Примеры паттерна, найденные в реальных системах.
Связанные паттерны
     Связи между паттернами, различия схожих.
Классификация паттернов

                           Назначение

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

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

                                                                       ●   Template Method

                  Объект    ●   Abstract Factory    ●   Adapter        ●   Chain of
                                                                           Responsibility
Набор паттернов




                            ●   Builder             ●   Bridge
                                                                       ●   Command
                            ●   Prototype           ●   Composite
                                                                       ●   Iterator
                            ●   Singleton           ●   Decorator
                                                                       ●   Mediator
                                                    ●   Facade
                                                                       ●   Memento
                                                    ●   Proxy
                                                                       ●   Flyweight

                                                                       ●   Observer

                                                                       ●   State

                                                                       ●   Strategy

                                                                       ●   Visitor
Паттерн Adapter
ОПРЕДЕЛЕНИЕ

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

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




                     Улетел на малую
                         Родину
Паттерн Adapter
Пример кода
/**                                                     /**
 * Vendor Interface                                      * Vendor new Implementation
 */                                                      */
interface EmailSubsribe                                 class AdidasEmailNew
{                                                       {
    public function subscribe(email);                       public function subscribe(email) { /* code */ }
    public function unsubscribe(email);                     public function unsubscribe(email) { /* code */ }
    public function sendUpdates();                          public function getSubscribers() { /* code */ }
}                                                           public function sendEmails(subscribers)
                                                            {
/**                                                           // Получить доступные обновления
 * Vendor Interface Implementation                            // Отослать всем всё
 */                                                         }
class AdidasEmail implements EmailSubsribe              }
{                                                       adidasEmailer = new AdidasEmailNew();
    public function subscribe(email) { /* code */ }     subscribers = adidasEmailer.getSubscribers();
    public function unsubscribe(email) { /* code */ }   adidasEmailer.sendEmails(subscribers);
    public function sendUpdates()
    {
      // Получить доступных подписчиков
      // Получить доступные обновления
      // Отослать всем всё
    }
}
adidasEmailer = new AdidasEmail();
adidasEmailer.sendUpdates();
Паттерн 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();
Паттерн Bridge
ОПРЕДЕЛЕНИЕ

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

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

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

Bridge паттерн полезен когда класс и то что он делает зачастую варьируются. Сам по себе
класс может быть представлен как реализация, а то что он делает - абстракция. Этот
паттерн можно так же представить как двухуровневая абстракция.
Паттерн Bridge
КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА BRIDGE

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

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

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

 ●   Конкретный Исполнитель
      ○   реализация Исполнителя
Паттерн Bridge
КЛАССИЧЕСКИЙ

                               Окно



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



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



С ПОМОЩЬЮ BRIDGE

                      Окно                                        Иконки



     Linux-Окно                 Mac-Окно              Для Linux             Для Mac
Паттерн Bridge
ПРИМЕР ИЗ ЖИЗНИ



                                отдел




                                сиcтем




                  Депозитный             Депозитный
                  калькулятор            калькулятор
                  для                    для
                  ПриватБанка            А-Банка
Паттерн Bridge
    Пример кода
/** "Implementor" */                                                         /** "Refined Abstraction" */
interface DrawingAPI {                                                       class CircleShape extends Shape {
   public void drawCircle(double x, double y, double radius);                  private double x, y, radius;
}                                                                              public CircleShape(double x, double y, double radius, DrawingAPI
                                                                             drawingAPI) {
/** "ConcreteImplementor" 1/2 */                                                  super(drawingAPI);
class DrawingAPI1 implements DrawingAPI {                                         this.x = x; this.y = y; this.radius = radius;
  public void drawCircle(double x, double y, double radius) {                  }
      System.out.printf("API1.circle at %f:%f radius %fn", x, y, radius);
  }                                                                              // low-level i.e. Implementation specific
}                                                                                public void draw() {
                                                                                      drawingAPI.drawCircle(x, y, radius);
/** "ConcreteImplementor" 2/2 */                                                 }
class DrawingAPI2 implements DrawingAPI {                                        // high-level i.e. Abstraction specific
  public void drawCircle(double x, double y, double radius) {                    public void resizeByPercentage(double pct) {
      System.out.printf("API2.circle at %f:%f radius %fn", x, y, radius);            radius *= pct;
  }                                                                              }
}                                                                            }

/** "Abstraction" */                                                         /** "Client" */
abstract class Shape {                                                       class BridgePattern {
  protected DrawingAPI drawingAPI;                                             public static void main(String[] args) {
                                                                                  Shape[] shapes = new Shape[] {
    protected Shape(DrawingAPI drawingAPI){                                          new CircleShape(1, 2, 3, new DrawingAPI1()),
      this.drawingAPI = drawingAPI;                                                  new CircleShape(5, 7, 11, new DrawingAPI2()),
    }                                                                             };

    public abstract void draw();                                                     for (Shape shape : shapes) {
    public abstract void resizeByPercentage(double pct);                               shape.resizeByPercentage(2.5);
}                                                                                      shape.draw();
                                                                                     }
                                                                                 }
                                                                             }
Паттерн Composite
ОПРЕДЕЛЕНИЕ

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

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

Ключевым игроком Паттерна композит является абстрактный класс, который представляет
как контейнер, так и примитив.
Паттерн Composite
КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА COMPOSITE

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

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

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

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




                                            примитивы
                                            (листки)
КЛАССИЧЕСКИ                        С ПОМОЩЬЮ COMPOSITE

layer = new Layer;                 layer = new Layer;
layer.elements = [                 layer.elements = [
   new Parallelogram(pParams),        new Parallelogram(pParams),
   new Ellipse(eParams),              new Ellipse(eParams),
   new Triangle(tParams)              new Triangle(tParams)
];                                 ];
layer.drawLayer();                 layer.draw();
each (layer.elements as element)
   element.drawElement();
Паттерн Composite
Пример кода
/** "Component" */                              /** "Leaf" */
interface Graphic                               class Ellipse implements Graphic
{                                               {
   public void print();                            public void print() {
}                                                    System.out.println("Ellipse");
                                                   }
/** "Composite" */                              }
import java.util.List;
import java.util.ArrayList;                     /** Client */
class CompositeGraphic implements Graphic       public class Program
{                                               {
   private List<Graphic> childGraphics = new      public static void main(String[] args) {
ArrayList<Graphic>();                                Ellipse ellipse1 = new Ellipse();
                                                     Ellipse ellipse2 = new Ellipse();
    public void print() {                            Ellipse ellipse3 = new Ellipse();
      for (Graphic graphic : childGraphics) {        Ellipse ellipse4 = new Ellipse();
         graphic.print();
      }                                                 CompositeGraphic graphic = new CompositeGraphic();
    }                                                   CompositeGraphic graphic1 = new CompositeGraphic();
                                                        CompositeGraphic graphic2 = new CompositeGraphic();
    public void add(Graphic graphic) {
      childGraphics.add(graphic);                       graphic1.add(ellipse1);
    }                                                   graphic1.add(ellipse2);
                                                        graphic1.add(ellipse3);
    public void remove(Graphic graphic) {
      childGraphics.remove(graphic);                    graphic2.add(ellipse4);
    }
}                                                       graphic.add(graphic1);
                                                        graphic.add(graphic2);

                                                        graphic.print();
                                                    }
                                                }
Паттерн Decorator
ОПРЕДЕЛЕНИЕ

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

Паттерн разработан так что бы множественне декораторы могли бы становитсья в стек
друг за другом, каждый раз добавляя новую функциональность для перегружаемых
(декорируемых) методов.
Паттерн Decorator
КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА DECORATOR

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

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

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

●   Конкретный Декоратор
     ○   добавляет функционао Компоненту
Паттерн Decorator
НА ПРИМЕРЕ ФОТОШОПЫ
Паттерн Decorator
ИЛИ БЕЗ ФОТОШОПЫ
Паттерн Composite
Пример кода
abstract class Window                                          @Override
{                                                              public void draw() {
                                                                 super.draw();
  public abstract void draw();
                                                                 drawVerticalScrollBar();
}
                                                               }

                                                               private void drawVerticalScrollBar() { /*code*/ }
class SimpleWindow extends Window                          }
{
   public void draw() { /*code*/ }                         class HorizontalScrollBarDecorator extends WindowDecorator
}                                                          {
                                                              public HorizontalScrollBarDecorator (Window
abstract class WindowDecorator extends Window              decoratedWindow) {
 {                                                              super(decoratedWindow);
   protected Window decoratedWindow;                          }

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

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

                                                               }
Паттерн Facade
ОПРЕДЕЛЕНИЕ

Паттерн проектирования Facade - позволяет скрыть сложность системы путем сведения
всех возможных вызовов к одному объекту, делегирующему их соответствующим
объектам системы. Реализация компонентов подситемы закрыта и не видна внешним
компонентам. Дизайн Facade-объекта защищает его от изменений в реализации
подсистемы.
Паттерн Facade
КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА FACADE

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

●   Подситемы
     ○   выполняет функциональность подситемы
     ○   выполняет работу, делегируеммую объектом Facade
     ○   не имеет представления о Facade, не имеет на него ссылок
Паттерн Facade
     ПРИМЕР ИЗ ЖИЗНИ
                                       Хочу стать частным предпринимателем


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




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




                             Другие                                                 Единое
                            службы**                                                 окно*




                                                            Банк



* - вопрос почему оно Единое и не единое на самом деле меня тоже гложжет
** - санстанция, лицензирование, пожарная безопастность и т. п.
Паттерн Proxy
ОПРЕДЕЛЕНИЕ

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

Существуют следующие разновидности паттерна:
 ● Протоколирующий прокси
 ● Удаленнй заместитель
 ● Виртуальный заместитель
 ● Копировать-при-записи
 ● Защищающий заместитель
 ● Кеширующий прокси
 ● Экранирующий прокси
 ● Синхронизирующий прокси
 ● Smart reference прокси
Паттерн Proxy
КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА FACADE

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

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

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




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

                  Firewall    Cache
                   Proxy      Proxy




                                      зерги
   Топ
менеджеры




  Другие
 клиенты
Паттерн Proxy
    Пример кода
interface IMath                                             class MathProxy implements IMath
{                                                            {
   function Add($x, $y);                                       protected $math;
   function Sub($x, $y);
   function Mul($x, $y);                                        public function __construct()
   function Div($x, $y);                                        {
}                                                                 $this->math = null;
                                                                }
class Math implements IMath
{                                                               public function Add($x, $y)
                                                                {
    public function   Add($x, $y){return $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;}              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));

More Related Content

Similar to Gang of four review.Structural patterns

Online TechTalk “Flutter Mobile Development”
Online TechTalk “Flutter Mobile Development”Online TechTalk “Flutter Mobile Development”
Online TechTalk “Flutter Mobile Development”GlobalLogic Ukraine
 
шаблоны проектирования
шаблоны проектированияшаблоны проектирования
шаблоны проектированияksmster
 
Общие темы. Тема 02.
Общие темы. Тема 02.Общие темы. Тема 02.
Общие темы. Тема 02.Igor Shkulipa
 
паттерны программирования
паттерны программированияпаттерны программирования
паттерны программированияguestfc8ae0
 
AOP and Design Patterns (GoF)
AOP and Design Patterns (GoF)AOP and Design Patterns (GoF)
AOP and Design Patterns (GoF)Andrey Gordienkov
 
Aspect Oriented Programming and Design Patterns
Aspect Oriented Programming and Design PatternsAspect Oriented Programming and Design Patterns
Aspect Oriented Programming and Design PatternsAndrey Gordienkov
 
Yuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practicesYuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practicesbeloslab
 
Проектирование программных систем. Занятие 9
Проектирование программных систем. Занятие 9Проектирование программных систем. Занятие 9
Проектирование программных систем. Занятие 9Dima Dzuba
 
UAFPUG6 - PureMVC
UAFPUG6 - PureMVCUAFPUG6 - PureMVC
UAFPUG6 - PureMVCmandrew182
 
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha DmitryUafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha DmitryMax Rozdobudko
 
ук 03.003.01 2011
ук 03.003.01 2011ук 03.003.01 2011
ук 03.003.01 2011etyumentcev
 
kranonit S15 Vladimir Melnik - Ruby on Rails, BDD
kranonit S15 Vladimir Melnik - Ruby on Rails, BDDkranonit S15 Vladimir Melnik - Ruby on Rails, BDD
kranonit S15 Vladimir Melnik - Ruby on Rails, BDDKrivoy Rog IT Community
 
Ігор Карпиленко — PHPStorm for drupal developer
Ігор Карпиленко — PHPStorm for drupal developerІгор Карпиленко — PHPStorm for drupal developer
Ігор Карпиленко — PHPStorm for drupal developerLEDC 2016
 
Модульная структура. Цветцих Денис D2D Just.NET
Модульная структура. Цветцих Денис D2D Just.NETМодульная структура. Цветцих Денис D2D Just.NET
Модульная структура. Цветцих Денис D2D Just.NETDev2Dev
 
Модульная структура
Модульная структураМодульная структура
Модульная структураDenis Tsvettsih
 

Similar to Gang of four review.Structural patterns (20)

DESIGN PATTERNS? EASY!
DESIGN PATTERNS? EASY!DESIGN PATTERNS? EASY!
DESIGN PATTERNS? EASY!
 
Online TechTalk “Flutter Mobile Development”
Online TechTalk “Flutter Mobile Development”Online TechTalk “Flutter Mobile Development”
Online TechTalk “Flutter Mobile Development”
 
шаблоны проектирования
шаблоны проектированияшаблоны проектирования
шаблоны проектирования
 
Общие темы. Тема 02.
Общие темы. Тема 02.Общие темы. Тема 02.
Общие темы. Тема 02.
 
Tdd php
Tdd phpTdd php
Tdd php
 
Software Design Patterns
Software Design PatternsSoftware Design Patterns
Software Design Patterns
 
паттерны программирования
паттерны программированияпаттерны программирования
паттерны программирования
 
AOP and Design Patterns (GoF)
AOP and Design Patterns (GoF)AOP and Design Patterns (GoF)
AOP and Design Patterns (GoF)
 
Aspect Oriented Programming and Design Patterns
Aspect Oriented Programming and Design PatternsAspect Oriented Programming and Design Patterns
Aspect Oriented Programming and Design Patterns
 
Yuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practicesYuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practices
 
The Best Portlet
The Best PortletThe Best Portlet
The Best Portlet
 
Проектирование программных систем. Занятие 9
Проектирование программных систем. Занятие 9Проектирование программных систем. Занятие 9
Проектирование программных систем. Занятие 9
 
UAFPUG6 - PureMVC
UAFPUG6 - PureMVCUAFPUG6 - PureMVC
UAFPUG6 - PureMVC
 
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha DmitryUafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
 
PureMVC and Papervision
PureMVC and PapervisionPureMVC and Papervision
PureMVC and Papervision
 
ук 03.003.01 2011
ук 03.003.01 2011ук 03.003.01 2011
ук 03.003.01 2011
 
kranonit S15 Vladimir Melnik - Ruby on Rails, BDD
kranonit S15 Vladimir Melnik - Ruby on Rails, BDDkranonit S15 Vladimir Melnik - Ruby on Rails, BDD
kranonit S15 Vladimir Melnik - Ruby on Rails, BDD
 
Ігор Карпиленко — PHPStorm for drupal developer
Ігор Карпиленко — PHPStorm for drupal developerІгор Карпиленко — PHPStorm for drupal developer
Ігор Карпиленко — PHPStorm for drupal developer
 
Модульная структура. Цветцих Денис D2D Just.NET
Модульная структура. Цветцих Денис D2D Just.NETМодульная структура. Цветцих Денис D2D Just.NET
Модульная структура. Цветцих Денис D2D Just.NET
 
Модульная структура
Модульная структураМодульная структура
Модульная структура
 

Gang of four review.Structural patterns

  • 1. Gang of four, the book review. Structural patterns
  • 2. Структура книги Книга разделена на две основные части. Превая часть (главы 1 и 2) описывает что есть паттерны проектирования и как они помогают решать вопросы проектирования ПО. Так же в ней включены примеры дизайна для наглядности применения паттернов проектирования на практике. Вторая часть книги (главы 3, 4, 5) - это непосредственно каталог паттернов. Каталог составляет основную часть книги. Все три главы второй части книги соответствуют трем разым типам паттернов, которые авторы разбили на три группы: ● паттерны создания, ● структурные паттерны, ● паттерны поведения. Авторы предлогают использовать книгу несколькими разными способами. От начала и до конца прочитать книгу и по очереди выучить все паттерны. Другой же способ заключается в изучении нужных Вам паттерном и, так как книга "усеяна" ссылками с одного паттерна на другой, то таким образом очень легко улавливать связи между паттернами, как они комбинируются и какие из них подходят друг к другу. Ссылки между книгами можно использовать как логический гайд по книге.
  • 3. Предмет книги Самой сложной частью дизайна объектно-ориентированных систем - это декомпозиция их на объекты. Эта задача сложна по многим причинам: энкапсуляция, детализация, зависимости, гибкость, производительность, перспективы развития, повторное использование, и т. д. Все это влияет на декомпозицию и зачастую, удовлетворение всех вышеупомянутых причин в дизайне системы, может приводить к конфликтам, например, более гибкая система наверняка будет иметь меньшую производительность. Подходов к проектированию объектно ориентированных систем - множество. Как вариант, вы можете написать утверждение, которое будет описывать Вашу систему, выделить существительные и глаголы и создать соответствующие классы с методами, на основе выделенных сущностей. Или Вы можете сфокусироваться на сотрудничестве и ответственностях в Вашей системе. Или Вы можете смоделировать "реальный мир" и перенести, найденные в нем в процессе анализа, объекты в дизайн Вашей системы. Всегда будут разногласия, какой подход лучше. Большинство объектов в дизайне порождается анализом модели. Но часто составление дизайна системы заканчивается на составлении класса, который не имеет предствления в реальном мире. Жесткое моделирование проблем реального мира приводит к тому что система вряд ли сможет решить проблемы "завтрашнего дня". Абстракции, появившиеся в процессе проектирования системы - ключ к гибкой системе. Паттерны проектирования помогают распознать менее очевидные абстракции и объекты, что, порожденные ими. К примеру, объекты, которые представляют процесс или алгоритм не встречаются в природе, однако они играют важную роль в составлении гибкой системы. Эти объекты редко находятся в процессе анализа или на ранних стадиях проектирования; они появляются позже - в процессе рефакторинга гибкости системы.
  • 4. Немного теории Каждая операция объявленная в объекте определяет имя метода, объекты которые этот метод использует в качестве параметров и результат, возвращаемый этим методом. Это так же известно как сигнатура операции. Набор всех сигнатур операций, определенных в объекте, называют Интерфейсом объекта. Интерфейс объекта характеризует набор запросов, которые можно запрашивать у объекта. Любой запрос, который удовлетворяет какую-либо сигнатуру в интерфейсе объекта, может быть запрошен у объекта. Тип - это имя, используемое для обозначения определенного интерфейса. Если говорить об объекте типа Окно, значит этот объект должен принимать все запросы, определенные в интерфейсе Окна. Объект может иметь много типов и абсолютно разные объекты могут иметь общие типы. Часть интерфейса объекта может характеризоваться одним типом, а другие части - другими типами. Тип является подтипом другого типа, если его интерфейс содержит подинтерфейс подтипа. Интерфейсы - основа объектно-ориентированных систем. Объекты общаются только через интерфейсы. Но интерфейсы ничего нам не говорят о реализации. Динамическое связывание гласит что делая запрос объекту, не требует Вашего представления о реализации, до рантайма. Более того, динамическое связывание позволяет заменять объекты с одинаковыми интерфейсами друг другом в райнтайме. Такие подмены называются полиморфизмом - ключевой концепцией ооп. Основываясь на вышесказанном, паттерны проектирования помогают Вам определить ключевые елементы в объявлении интерфейсов, а так же исключать не нужные элементы.
  • 5. Структура описания паттерна Название паттерна Название паттерна кратко передает сущность идеи. Правильно имя важно, так как оно становится частью Вашего словаря паттернов. Намерение Небольшая секция, отвечающая на вопрос: что делает данный паттерн? Каковы его обоснования и цель? какой конкретный вопрос дизайна он решает? Так же известен как Альтернативные названия паттерна. Мотивация Сценарий, описывающий проблему дизайна и как объектная структура паттерна решает проблему. Применение Ситуации в которых применение паттерна наиболее обосновано? Примеры плохого дизайна которые решает паттерн. Методы распознавания таких ситуаций. Структура Графическое представление классов в рассматриваемом паттерне. Участники Классы и/или объекты, участвующие в дизайне паттерна и их ответственность. Сотрудничество Взаимодействие участников для достижения цели. Последствия Компромиссы и результаты использования шаблона. Применение Тонкости и техники о коих нужно знать при использовании шаблона. Пример кода Примеры применения паттерна на C++ или Smalltalk. Известные проблемы Примеры паттерна, найденные в реальных системах. Связанные паттерны Связи между паттернами, различия схожих.
  • 6. Классификация паттернов Назначение Создание Структурирование Поведение Класс ● Factory Method ● Adapter ● Interpreter ● Template Method Объект ● Abstract Factory ● Adapter ● Chain of Responsibility Набор паттернов ● Builder ● Bridge ● Command ● Prototype ● Composite ● Iterator ● Singleton ● Decorator ● Mediator ● Facade ● Memento ● Proxy ● Flyweight ● Observer ● State ● Strategy ● Visitor
  • 7. Паттерн Adapter ОПРЕДЕЛЕНИЕ Паттерн проектирования Адаптер упрощает взаимоотношения, путем адаптирования изменений в текущем функционале. Коротко говоря, для его реализации необходимо определить интерфейс, который поможет интегрировать несовместимые компоненты. Из Wikipedia: "В программировании, паттерн адаптер это один из шаблонов проектирования, который превращает некий интерфейс класса в совместимый интерфейс. Адаптер позволяет классам работать сообща в случаях, когда это невозможно из-за несовместимости интерфейсов, предоставляя клиенту свой интерфейс, в то время как сам по себе он использует оригинальный интерфейс."
  • 8. Паттерн Adapter ПРИМЕР ИЗ ЖИЗНИ Улетел на малую Родину
  • 9. Паттерн Adapter Пример кода /** /** * Vendor Interface * Vendor new Implementation */ */ interface EmailSubsribe class AdidasEmailNew { { public function subscribe(email); public function subscribe(email) { /* code */ } public function unsubscribe(email); public function unsubscribe(email) { /* code */ } public function sendUpdates(); public function getSubscribers() { /* code */ } } public function sendEmails(subscribers) { /** // Получить доступные обновления * Vendor Interface Implementation // Отослать всем всё */ } class AdidasEmail implements EmailSubsribe } { adidasEmailer = new AdidasEmailNew(); public function subscribe(email) { /* code */ } subscribers = adidasEmailer.getSubscribers(); public function unsubscribe(email) { /* code */ } adidasEmailer.sendEmails(subscribers); public function sendUpdates() { // Получить доступных подписчиков // Получить доступные обновления // Отослать всем всё } } adidasEmailer = new AdidasEmail(); adidasEmailer.sendUpdates();
  • 10. Паттерн 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();
  • 11. Паттерн Bridge ОПРЕДЕЛЕНИЕ Когда абстакция может иметь одну из возможных реализаций, классическим способом согласовать их - это использовать наследование. Абстрактный класс определяет интерфейс абстракции и конкретный класс реализует его своим способом. Но такой не является достаточно гибким. Наследование неизменно связывает реализацию с абстракцией, что делает эту связку трудно поддающуюся модификациям, расширению, повторному использованию абстракции и реализации отдельно друг от друга. Паттерн проектирования Bridge производит декомпозицию абстракции от ее реализации так, что бы они могли существовать независимо друг от друга. Паттерн Bridge использует инкапсуляцию, агрегацию и может использовать наследования, для разделения полномочий в разных классах. Bridge паттерн полезен когда класс и то что он делает зачастую варьируются. Сам по себе класс может быть представлен как реализация, а то что он делает - абстракция. Этот паттерн можно так же представить как двухуровневая абстракция.
  • 12. Паттерн Bridge КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА BRIDGE ● Абстракция ○ определяет интерфейс абстракции ○ содержит ссылку на объект типа Исполнитель ● Модернизированная Абстракция ○ расширяет интерфейс, определенный абстракцией ● Исполнитель ○ определяет интерфейс для классов-сателитов ● Конкретный Исполнитель ○ реализация Исполнителя
  • 13. Паттерн Bridge КЛАССИЧЕСКИЙ Окно Linux-Окно Mac-Окно Окно-с-иконкой Linux-Окно-с-иконкой Mac-Окно-с-иконкой С ПОМОЩЬЮ BRIDGE Окно Иконки Linux-Окно Mac-Окно Для Linux Для Mac
  • 14. Паттерн Bridge ПРИМЕР ИЗ ЖИЗНИ отдел сиcтем Депозитный Депозитный калькулятор калькулятор для для ПриватБанка А-Банка
  • 15. Паттерн Bridge Пример кода /** "Implementor" */ /** "Refined Abstraction" */ interface DrawingAPI { class CircleShape extends Shape { public void drawCircle(double x, double y, double radius); private double x, y, radius; } public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) { /** "ConcreteImplementor" 1/2 */ super(drawingAPI); class DrawingAPI1 implements DrawingAPI { this.x = x; this.y = y; this.radius = radius; public void drawCircle(double x, double y, double radius) { } System.out.printf("API1.circle at %f:%f radius %fn", x, y, radius); } // low-level i.e. Implementation specific } public void draw() { drawingAPI.drawCircle(x, y, radius); /** "ConcreteImplementor" 2/2 */ } class DrawingAPI2 implements DrawingAPI { // high-level i.e. Abstraction specific public void drawCircle(double x, double y, double radius) { public void resizeByPercentage(double pct) { System.out.printf("API2.circle at %f:%f radius %fn", x, y, radius); radius *= pct; } } } } /** "Abstraction" */ /** "Client" */ abstract class Shape { class BridgePattern { protected DrawingAPI drawingAPI; public static void main(String[] args) { Shape[] shapes = new Shape[] { protected Shape(DrawingAPI drawingAPI){ new CircleShape(1, 2, 3, new DrawingAPI1()), this.drawingAPI = drawingAPI; new CircleShape(5, 7, 11, new DrawingAPI2()), } }; public abstract void draw(); for (Shape shape : shapes) { public abstract void resizeByPercentage(double pct); shape.resizeByPercentage(2.5); } shape.draw(); } } }
  • 16. Паттерн Composite ОПРЕДЕЛЕНИЕ Паттерн Composite собирает объекты в структуру бинарного дерева для представления иерархической структуры. Он так же позволяет клиенту обращаться с отдельными объектами и композициями объектов в одном формате. В иерархических структурах код для работы с контейнерами и примитивами зачастую отличается, даже если, в основном, обращения одинаковы. Разделив эти объекты, приложение усложняется. Паттерн Composite описывает как использовать рекурсивную композицию, что бы для клиентов не было отличия между контейнерами и примитивами. Пример: графический редактор. Ключевым игроком Паттерна композит является абстрактный класс, который представляет как контейнер, так и примитив.
  • 17. Паттерн Composite КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА COMPOSITE ● Компонент ○ определяет интерфейс для объектов композиции ○ реализует стандартное поведение для интерфейса, общего для всех классов ○ определяет интерфейс для доступа и управления дочерними листками ○ [не обязательно] определяет интерфейс для рекурсивного доступа к родителям в Композиции ● Листок ○ представляет объекты Листков в Композиции. Листок не имеет наследников ○ определяет поведение примитивов в Композиции ● Композиция ○ определяет поведение для компонентов, имеющих наследников ○ имеет наследников ○ реализует методы дочерних элементов через интерфейс Компоненты ● Клиент ○ управляет объектами Композиции через интерфейс Компоненты
  • 18. Паттерн Composite слой (композиция) примитивы (листки) КЛАССИЧЕСКИ С ПОМОЩЬЮ COMPOSITE layer = new Layer; layer = new Layer; layer.elements = [ layer.elements = [ new Parallelogram(pParams), new Parallelogram(pParams), new Ellipse(eParams), new Ellipse(eParams), new Triangle(tParams) new Triangle(tParams) ]; ]; layer.drawLayer(); layer.draw(); each (layer.elements as element) element.drawElement();
  • 19. Паттерн Composite Пример кода /** "Component" */ /** "Leaf" */ interface Graphic class Ellipse implements Graphic { { public void print(); public void print() { } System.out.println("Ellipse"); } /** "Composite" */ } import java.util.List; import java.util.ArrayList; /** Client */ class CompositeGraphic implements Graphic public class Program { { private List<Graphic> childGraphics = new public static void main(String[] args) { ArrayList<Graphic>(); Ellipse ellipse1 = new Ellipse(); Ellipse ellipse2 = new Ellipse(); public void print() { Ellipse ellipse3 = new Ellipse(); for (Graphic graphic : childGraphics) { Ellipse ellipse4 = new Ellipse(); graphic.print(); } CompositeGraphic graphic = new CompositeGraphic(); } CompositeGraphic graphic1 = new CompositeGraphic(); CompositeGraphic graphic2 = new CompositeGraphic(); public void add(Graphic graphic) { childGraphics.add(graphic); graphic1.add(ellipse1); } graphic1.add(ellipse2); graphic1.add(ellipse3); public void remove(Graphic graphic) { childGraphics.remove(graphic); graphic2.add(ellipse4); } } graphic.add(graphic1); graphic.add(graphic2); graphic.print(); } }
  • 20. Паттерн Decorator ОПРЕДЕЛЕНИЕ Добавляет дополнительные возможности объекту динамически. Паттерн декоратор предоставляет гибкую альтернативу наследованию, для более гибкоого расширения функционала. Паттерн разработан так что бы множественне декораторы могли бы становитсья в стек друг за другом, каждый раз добавляя новую функциональность для перегружаемых (декорируемых) методов.
  • 21. Паттерн Decorator КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА DECORATOR ● Компонент ○ определяет интерфейс для объектов, которые смогут динамически добавлять функциональность ● Конкретный компонент ○ определяет объект, которому можно добавлять функционал ● Декоратор ○ определяет интерфейс для объектов которые смогут добавлять себе функционал динамически ○ хранит ссылку на объект-Компонент и определяет интерфейс, который соответствует интерфейсу Компонента ● Конкретный Декоратор ○ добавляет функционао Компоненту
  • 24. Паттерн Composite Пример кода abstract class Window @Override { public void draw() { super.draw(); public abstract void draw(); drawVerticalScrollBar(); } } private void drawVerticalScrollBar() { /*code*/ } class SimpleWindow extends Window } { public void draw() { /*code*/ } class HorizontalScrollBarDecorator extends WindowDecorator } { public HorizontalScrollBarDecorator (Window abstract class WindowDecorator extends Window decoratedWindow) { { super(decoratedWindow); protected Window decoratedWindow; } public WindowDecorator (Window decoratedWindow) { @Override this.decoratedWindow = decoratedWindow; public void draw() { } super.draw(); drawHorizontalScrollBar(); public void draw() { } decoratedWindow.draw(); } private void drawHorizontalScrollBar() { /*code*/ } } } class VerticalScrollBarDecorator extends WindowDecorator public class DecoratedWindowTest { { public VerticalScrollBarDecorator (Window public static void main(String[] args) { decoratedWindow) Window decoratedWindow = new { HorizontalScrollBarDecorator ( super(decoratedWindow); new VerticalScrollBarDecorator(new } SimpleWindow())); }
  • 25. Паттерн Facade ОПРЕДЕЛЕНИЕ Паттерн проектирования Facade - позволяет скрыть сложность системы путем сведения всех возможных вызовов к одному объекту, делегирующему их соответствующим объектам системы. Реализация компонентов подситемы закрыта и не видна внешним компонентам. Дизайн Facade-объекта защищает его от изменений в реализации подсистемы.
  • 26. Паттерн Facade КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА FACADE ● Фасад ○ знает какие части подсистемы ответственны за выполнения запроса ○ делегирует клиентские запросы соответствующим подсистемам ● Подситемы ○ выполняет функциональность подситемы ○ выполняет работу, делегируеммую объектом Facade ○ не имеет представления о Facade, не имеет на него ссылок
  • 27. Паттерн Facade ПРИМЕР ИЗ ЖИЗНИ Хочу стать частным предпринимателем Куда податься ? ? Пенсионный Налоговая фонд Другие Единое службы** окно* Банк * - вопрос почему оно Единое и не единое на самом деле меня тоже гложжет ** - санстанция, лицензирование, пожарная безопастность и т. п.
  • 28. Паттерн Proxy ОПРЕДЕЛЕНИЕ Паттерн проектирования Proxy - предоставляет объект, который контролирует доступ к другому объекту, перехватывая все его вызовы (выполняет функции контейнера). Существуют следующие разновидности паттерна: ● Протоколирующий прокси ● Удаленнй заместитель ● Виртуальный заместитель ● Копировать-при-записи ● Защищающий заместитель ● Кеширующий прокси ● Экранирующий прокси ● Синхронизирующий прокси ● Smart reference прокси
  • 29. Паттерн Proxy КЛЮЧЕВЫЕ КОМПОНЕНТЫ ПАТТЕРНА FACADE ● Субъект ○ интерфейс, определяющий поведение Реального субъекта ● Реальный субъект ○ реализует тип субъекта ● Proxy (Заместитель) ○ реализует тип субъекта ○ дает возможность добавлять поведение в проксируемый объект
  • 30. Паттерн Proxy ПРИМЕР ИЗ ЖИЗНИ Бизнеса банка Firewall Cache Proxy Proxy зерги Топ менеджеры Другие клиенты
  • 31. Паттерн Proxy Пример кода interface IMath class MathProxy implements IMath { { function Add($x, $y); protected $math; function Sub($x, $y); function Mul($x, $y); public function __construct() function Div($x, $y); { } $this->math = null; } class Math implements IMath { public function Add($x, $y) { public function Add($x, $y){return $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;} 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));