Patterns Flashcards

1
Q

Виды шаблонов

A

1, Порождающие.

  1. Структурные.
  2. Поведенческие.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Порождающие шаблоны

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Список порождающих шаблонов

A
  • простая фабрика (Simple Factory);
  • фабричный метод (Factory Method);
  • абстрактная фабрика (Abstract Factory);
  • строитель (Builder);
  • прототип (Prototype);
  • одиночка (Singleton).
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

В объектно-ориентированном программировании (ООП), фабрика — это…

A

объект для создания других объектов. Формально фабрика — это функция или метод, который возвращает объекты изменяющегося прототипа или класса из некоторого вызова метода, который считается «новым».

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

SimpleFactory - пример

A
interface Door
{
    public function getWidth(): float;
    public function getHeight(): float;
}

class WoodenDoor implements Door
{
protected $width;
protected $height;

    public function \_\_construct(float $width, float $height)
    {
        $this->width = $width;
        $this->height = $height;
    }
public function getWidth(): float
{
    return $this->width;
}
    public function getHeight(): float
    {
        return $this->height;
    }
}
class DoorFactory
{
    public static function makeDoor($width, $height): Door
    {
        return new WoodenDoor($width, $height);
    }
}

$door = DoorFactory::makeDoor(100, 200);
echo ‘Width: ‘ . $door->getWidth();
echo ‘Height: ‘ . $door->getHeight();

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Когда использовать SimpleFactory

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

FactoryMethod - это…

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

FactoryMethod - пример…

A

interface Interviewer
{
public function askQuestions();
}

class Developer implements Interviewer
{
    public function askQuestions()
    {
        echo 'Спрашивает про шаблоны проектирования!';
    }
}
class CommunityExecutive implements Interviewer
{
    public function askQuestions()
    {
        echo 'Спрашивает о работе с сообществом';
    }
}
abstract class HiringManager
{
    // Фабричный метод
    abstract public function makeInterviewer(): Interviewer;
    public function takeInterview()
    {
        $interviewer = $this->makeInterviewer();
        $interviewer->askQuestions();
    }
}
class DevelopmentManager extends HiringManager
{
    public function makeInterviewer(): Interviewer
    {
        return new Developer();
    }
}
class MarketingManager extends HiringManager
{
    public function makeInterviewer(): Interviewer
    {
        return new CommunityExecutive();
    }
}
$devManager = new DevelopmentManager();
$devManager->takeInterview(); // Вывод: Спрашивает о шаблонах проектирования!
$marketingManager = new MarketingManager();
$marketingManager->takeInterview(); // Вывод:
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Когда использовать FactoryMethod

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

AbstractFactory — это

A

порождающий шаблон проектирования, предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов. Шаблон реализуется созданием абстрактного класса Factory, который представляет собой интерфейс для создания компонентов системы (например, для оконного интерфейса он может создавать окна и кнопки). Затем пишутся классы, реализующие этот интерфейс.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

AbstractFactory - пример

A

interface Door
{
public function getDescription();
}

class WoodenDoor implements Door
{
    public function getDescription()
    {
        echo 'Я деревянная дверь';
    }
}
class IronDoor implements Door
{
    public function getDescription()
    {
        echo 'Я железная дверь';
    }
}

interface DoorFittingExpert
{
public function getDescription();
}

class Welder implements DoorFittingExpert
{
    public function getDescription()
    {
        echo 'Я работаю только с железными дверьми';
    }
}
class Carpenter implements DoorFittingExpert
{
    public function getDescription()
    {
        echo 'Я работаю только с деревянными дверьми';
    }
}
interface DoorFactory
{
    public function makeDoor(): Door;
    public function makeFittingExpert(): DoorFittingExpert;
}
// Деревянная фабрика вернет деревянную дверь и столяра
class WoodenDoorFactory implements DoorFactory
{
    public function makeDoor(): Door
    {
        return new WoodenDoor();
    }
    public function makeFittingExpert(): DoorFittingExpert
    {
        return new Carpenter();
    }
}
// Железная фабрика вернет железную дверь и сварщика
class IronDoorFactory implements DoorFactory
{
    public function makeDoor(): Door
    {
        return new IronDoor();
    }
    public function makeFittingExpert(): DoorFittingExpert
    {
        return new Welder();
    }
}

$woodenFactory = new WoodenDoorFactory();

$door = $woodenFactory->makeDoor();
$expert = $woodenFactory->makeFittingExpert();

$door->getDescription(); // Вывод: Я деревянная дверь
$expert->getDescription(); // Вывод: Я работаю только с деревянными дверями

// Аналогично для железной двери
$ironFactory = new IronDoorFactory();
$door = $ironFactory->makeDoor();
$expert = $ironFactory->makeFittingExpert();

$door->getDescription(); // Вывод: Я железная дверь
$expert->getDescription(); // Вывод: Я работаю только с железными дверями

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

AbstractFactory - когда использовать

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Builder - это

A

порождающий шаблон проектирования, который предоставляет способ создания составного объекта. Предназначен для решения проблемы антипаттерна «Телескопический конструктор».

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Builder - пример

A
class Burger
{
    protected $size;
protected $cheese = false;
protected $pepperoni = false;
protected $lettuce = false;
protected $tomato = false;

public function \_\_construct(BurgerBuilder $builder)
{
    $this->size = $builder->size;
    $this->cheese = $builder->cheese;
    $this->pepperoni = $builder->pepperoni;
    $this->lettuce = $builder->lettuce;
    $this->tomato = $builder->tomato;
} }
class BurgerBuilder
{
    public $size;
public $cheese = false;
public $pepperoni = false;
public $lettuce = false;
public $tomato = false;

public function \_\_construct(int $size)
{
    $this->size = $size;
}
    public function addPepperoni()
    {
        $this->pepperoni = true;
        return $this;
    }
    public function addLettuce()
    {
        $this->lettuce = true;
        return $this;
    }
    public function addCheese()
    {
        $this->cheese = true;
        return $this;
    }
    public function addTomato()
    {
        $this->tomato = true;
        return $this;
    }
    public function build(): Burger
    {
        return new Burger($this);
    }
}

$burger = (new BurgerBuilder(14))

                - >addPepperoni()
                - >addLettuce()
                - >addTomato()
                - >build();
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Когда использовать Builder

A

Когда может быть несколько видов объекта и надо избежать «телескопического конструктора». Главное отличие от «фабрики» — это то, что она используется, когда создание занимает один шаг, а «строитель» применяется при множестве шагов.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Prototype - это

A

Задаёт виды создаваемых объектов с помощью экземпляра-прототипа и создаёт новые объекты путём копирования этого прототипа. Он позволяет уйти от реализации и позволяет следовать принципу «программирование через интерфейсы». В качестве возвращающего типа указывается интерфейс / абстрактный класс на вершине иерархии, а классы-наследники могут подставить туда наследника, реализующего этот тип.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Prototype - пример

A

class Sheep
{
protected $name;
protected $category;

    public function \_\_construct(string $name, string $category = 'Горная овечка')
    {
        $this->name = $name;
        $this->category = $category;
    }
public function setName(string $name)
{
    $this->name = $name;
}

public function getName()
{
    return $this->name;
}

public function setCategory(string $category)
{
    $this->category = $category;
}
    public function getCategory()
    {
        return $this->category;
    }
}

$original = new Sheep(‘Джолли’);
echo $original->getName(); // Джолли
echo $original->getCategory(); // Горная овечка

// Клонируем и модифицируем то что нужно
$cloned = clone $original;
$cloned->setName('Долли');
echo $cloned->getName(); // Долли
echo $cloned->getCategory(); // Горная овечка
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

Prototype - когда использовать

A

Когда необходим объект, похожий на существующий объект, либо когда создание будет дороже клонирования.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Singleton - это

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

Singleton - пример

A
final class President
{
    private static $instance;
    private function \_\_construct()
    {
        // Прячем конструктор
    }
    public static function getInstance(): President
    {
        if (!self::$instance) {
            self::$instance = new self();
        }
    return self::$instance;
}
    private function \_\_clone()
    {
        // Отключаем клонирование
    }
    private function \_\_wakeup()
    {
        // Отключаем десериализацию
    }
}
$president1 = President::getInstance();
$president2 = President::getInstance();

var_dump($president1 === $president2); // true

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

Структурные шаблоны

A

шаблоны проектирования, в которых рассматривается вопрос о том, как из классов и объектов образуются более крупные структуры.

Структурные шаблоны в основном связаны с композицией объектов, другими словами, с тем, как сущности могут использовать друг друга. Ещё одним объяснением было бы то, что они помогают ответить на вопрос «Как создать программный компонент?».

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

Список структурных шаблонов проектирования

A
  • адаптер (Adapter);
  • мост (Bridge);
  • компоновщик (Composite);
  • декоратор (Decorator);
  • фасад (Facade);
  • приспособленец (Flyweight);
  • заместитель (Proxy).
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Adapter - это

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

Adapter - пример

A

interface Lion
{
public function roar();
}

class AfricanLion implements Lion
{
    public function roar()
    {
    }
}
class AsianLion implements Lion
{
    public function roar()
    {
    }
}
class Hunter
{
    public function hunt(Lion $lion)
    {
    }
}
// Это надо добавить в игру
class WildDog
{
    public function bark()
    {
    }
}

// Адаптер, чтобы сделать WildDog совместимой с нашей игрой class WildDogAdapter implements Lion { protected $dog; public function __construct(WildDog $dog) { $this->dog = $dog; } public function roar() { $this->dog->bark(); } }

$wildDog = new WildDog();
$wildDogAdapter = new WildDogAdapter($wildDog);
$hunter = new Hunter();
$hunter->hunt($wildDogAdapter);
25
Q

Bridge - это

A

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

26
Q

Bridge - пример

A
interface WebPage
{
    public function \_\_construct(Theme $theme);
    public function getContent();
}
class About implements WebPage
{
    protected $theme;
public function \_\_construct(Theme $theme)
{
    $this->theme = $theme;
}
    public function getContent()
    {
        return "Страница с информацией в " . $this->theme->getColor();
    }
}
class Careers implements WebPage
{
    protected $theme;
public function \_\_construct(Theme $theme)
{
    $this->theme = $theme;
}
    public function getContent()
    {
        return "Страница карьеры в " . $this->theme->getColor();
    }
}

interface Theme
{
public function getColor();
}

class DarkTheme implements Theme
{
    public function getColor()
    {
        return 'темной теме';
    }
}
class LightTheme implements Theme
{
    public function getColor()
    {
        return 'светлой теме';
    }
}
class AquaTheme implements Theme
{
    public function getColor()
    {
        return 'голубой теме';
    }
}

$darkTheme = new DarkTheme();

$about = new About($darkTheme);
$careers = new Careers($darkTheme);

echo $about->getContent(); // “Страница информации в темной теме”;
echo $careers->getContent(); // “Страница карьеры в темной теме”;

27
Q

Компоновщик - это

A

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

28
Q

Компоновщик - пример

A

interface Assignee {
public function canHandleTask($task): bool;
public function takeTask($task);
}

class Employee implements Assignee {
  // реализуем методы интерфейса
}
class Team implements Assignee {
  /** @var Assignee[] */
  private $assignees;
  // вспомогательные методы для управления композитом:
  public function add($assignee);
  public function remove($assignee);

// метода интерфейса Employee

  public function canHandleTask($task): bool {
    foreach ($this->assignees as $assignee) if ($assignee->canHandleTask($task)) return true;
    return false;
  }
  public function takeTask($task) {
    // может быть разная имплементация - допустим, некоторые задания требуют нескольких человек из команды одновременно
    // в простейшем случае берем первого незанятого работника среди this->assignees
    $assignee = ...;
    $assignee->takeTask($task);
  }
}
class TaskManager {
  private $assignees;
  public function performTask($task) {
    foreach ($this->assignees as $assignee) {
       if ($assignee->canHandleTask($task)) {
         $assignee->takeTask($task);
         return;
       }
    }
    throw new Exception('Cannot handle the task - please hire more people');
  }
}
$employee1 = new Employee();
$employee2 = new Employee();
$employee3 = new Employee();
$employee4 = new Employee();
$team1 = new Team([$employee3, $employee4);
// ВНИМАНИЕ: передаем команду в taskManager как единый композит.
// Сам taskManager не знает, что это команда и работает с ней без модификации своей логики.
$taskManager = new TaskManager([$employee1, $employee2, $team1]);
$taskManager->preformTask($task);
29
Q

Decorator - это

A

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

30
Q

Decorator - пример

A
interface Coffee
{
    public function getCost();
    public function getDescription();
}
class SimpleCoffee implements Coffee
{
    public function getCost()
    {
        return 10;
    }
    public function getDescription()
    {
        return 'Простой кофе';
    }
}
class MilkCoffee implements Coffee
{
    protected $coffee;
public function \_\_construct(Coffee $coffee)
{
    $this->coffee = $coffee;
}

public function getCost()
{
    return $this->coffee->getCost() + 2;
}
    public function getDescription()
    {
        return $this->coffee->getDescription() . ', молоко';
    }
}
class WhipCoffee implements Coffee
{
    protected $coffee;
public function \_\_construct(Coffee $coffee)
{
    $this->coffee = $coffee;
}

public function getCost()
{
    return $this->coffee->getCost() + 5;
}
    public function getDescription()
    {
        return $this->coffee->getDescription() . ', сливки';
    }
}
class VanillaCoffee implements Coffee
{
    protected $coffee;
public function \_\_construct(Coffee $coffee)
{
    $this->coffee = $coffee;
}

public function getCost()
{
    return $this->coffee->getCost() + 3;
}
    public function getDescription()
    {
        return $this->coffee->getDescription() . ', ваниль';
    }
}

$someCoffee = new SimpleCoffee();
echo $someCoffee->getCost(); // 10
echo $someCoffee->getDescription(); // Простой кофе

$someCoffee = new MilkCoffee($someCoffee);
echo $someCoffee->getCost(); // 12
echo $someCoffee->getDescription(); // Простой кофе, молоко

$someCoffee = new WhipCoffee($someCoffee);
echo $someCoffee->getCost(); // 17
echo $someCoffee->getDescription(); // Простой кофе, молоко, сливки

$someCoffee = new VanillaCoffee($someCoffee);
echo $someCoffee->getCost(); // 20
echo $someCoffee->getDescription(); // Простой кофе, молоко, сливки, ваниль

31
Q

Facade - это

A

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

32
Q

Facade - пример

A
class Computer
{
    public function getElectricShock()
    {
        echo "Ай!";
    }
public function makeSound()
{
    echo "Бип-бип!";
}

public function showLoadingScreen()
{
    echo "Загрузка..";
}

public function bam()
{
    echo "Готов к использованию!";
}

public function closeEverything()
{
    echo "Буп-буп-буп-бззз!";
}

public function sooth()
{
    echo "Zzzzz";
}
    public function pullCurrent()
    {
        echo "Аах!";
    }
}
class ComputerFacade
{
    protected $computer;
public function \_\_construct(Computer $computer)
{
    $this->computer = $computer;
}

public function turnOn()
{
    $this->computer->getElectricShock();
    $this->computer->makeSound();
    $this->computer->showLoadingScreen();
    $this->computer->bam();
}
    public function turnOff()
    {
        $this->computer->closeEverything();
        $this->computer->pullCurrent();
        $this->computer->sooth();
    }
}

$computer = new ComputerFacade(new Computer());
$computer->turnOn(); // Ай! Бип-бип! Загрузка.. Готов к использованию!
$computer->turnOff(); // Буп-буп-буп-бззз! Аах! Zzzzz

33
Q

Flyweight - это

A

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

34
Q

Flyweight - пример

A
// Все, что будет закешировано, является приспособленцем.
// Типы чая здесь будут приспособленцами.
class KarakTea
{
}
//Ведет себя как фабрика и сохраняет чай
class TeaMaker
{
    protected $availableTea = [];
    public function make($preference)
    {
        if (empty($this->availableTea[$preference])) {
            $this->availableTea[$preference] = new KarakTea();
        }
    return $this->availableTea[$preference];
} }

class TeaShop
{
protected $orders;
protected $teaMaker;

public function \_\_construct(TeaMaker $teaMaker)
{
    $this->teaMaker = $teaMaker;
}

public function takeOrder(string $teaType, int $table)
{
    $this->orders[$table] = $this->teaMaker->make($teaType);
}

public function serve()
{
    foreach ($this->orders as $table => $tea) {
        echo "Serving tea to table# " . $table;
    }
} }
$teaMaker = new TeaMaker();
$shop = new TeaShop($teaMaker);

$shop->takeOrder(‘меньше сахара’, 1);
$shop->takeOrder(‘больше молока’, 2);
$shop->takeOrder(‘без сахара’, 5);

$shop->serve();
// Подаем чай на первый стол
// Подаем чай на второй стол
// Подаем чай на пятый стол
35
Q

Proxy - это

A

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

36
Q

Proxy - пример

A
interface Door
{
    public function open();
    public function close();
}
class LabDoor implements Door
{
    public function open()
    {
        echo "Открытие дверь лаборатории";
    }
    public function close()
    {
        echo "Закрытие двери лаборатории";
    }
}
class Security
{
    protected $door;
public function \_\_construct(Door $door)
{
    $this->door = $door;
}
    public function open($password)
    {
        if ($this->authenticate($password)) {
            $this->door->open();
        } else {
            echo "Нет! Это невозможно.";
        }
    }
public function authenticate($password)
{
    return $password === '$ecr@t';
}
    public function close()
    {
        $this->door->close();
    }
}
$door = new Security(new LabDoor());
$door->open('invalid'); // Нет! Это невозможно.

$door->open(‘$ecr@t’); // Открытие двери лаборатории
$door->close(); // Закрытие двери лаборатории

37
Q

Поведенческие шаблоны

A

шаблоны проектирования, определяющие алгоритмы и способы реализации взаимодействия различных объектов и классов. Простыми словами; Поведенческие шаблоны связаны с распределением обязанностей между объектами. Их отличие от структурных шаблонов заключается в том, что они не просто описывают структуру, но также описывают шаблоны для передачи сообщений / связи между ними. Или, другими словами, они помогают ответить на вопрос «Как запустить поведение в программном компоненте?»

38
Q

Поведенческие шаблоны - список

A
  • цепочка обязанностей (Chain of Responsibility);
  • команда (Command);
  • итератор (Iterator);
  • посредник (Mediator);
  • хранитель (Memento);
  • наблюдатель (Observer);
  • посетитель (Visitor);
  • стратегия (Strategy);
  • состояние (State);
  • шаблонный метод (Template Method).
39
Q

Chain of Responsibility - это

A

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

40
Q

Chain of Responsibility - пример

A

abstract class Account
{
protected $successor;
protected $balance;

public function setNext(Account $account)
{
    $this->successor = $account;
}
    public function pay(float $amountToPay)
    {
        if ($this->canPay($amountToPay)) {
            echo sprintf('Оплата %s, используя %s' . PHP_EOL, $amountToPay, get_called_class());
        } elseif ($this->successor) {
            echo sprintf('Нельзя заплатить, используя %s. Обработка ..' . PHP_EOL, get_called_class());
            $this->successor->pay($amountToPay);
        } else {
            throw new Exception('Ни на одном из аккаунтов нет необходимого количества денег');
        }
    }
public function canPay($amount): bool
{
    return $this->balance >= $amount;
} }
class Bank extends Account
{
    protected $balance;
    public function \_\_construct(float $balance)
    {
        $this->balance = $balance;
    }
}
class Paypal extends Account
{
    protected $balance;
    public function \_\_construct(float $balance)
    {
        $this->balance = $balance;
    }
}
class Bitcoin extends Account
{
    protected $balance;
    public function \_\_construct(float $balance)
    {
        $this->balance = $balance;
    }
}
// Подготовим цепь
//      $bank->$paypal->$bitcoin
//
// Первый по приоритету банк
//      Если нельзя через банк, то Paypal
//      Если нельзя через Paypal, то Bitcoin
$bank = new Bank(100);          // Банк с балансом 100
$paypal = new Paypal(200);      // Paypal с балансом 200
$bitcoin = new Bitcoin(300);    // Bitcoin с балансом 300

$bank->setNext($paypal);
$paypal->setNext($bitcoin);

// Попробуем оплатить через банк
$bank->pay(259);
// Вывод
// ==============
// Нельзя заплатить, используя Банк. Обработка ..
// Нельзя заплатить, используя Paypal. Обработка ..:
// Оплата 259, используя Bitcoin!
41
Q

Command - это

A

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

42
Q

Command - пример

A
class Bulb
{
    public function turnOn()
    {
        echo "Лампочка загорелась";
    }
    public function turnOff()
    {
        echo "Темнота!";
    }
}
interface Command
{
    public function execute();
    public function undo();
    public function redo();
}
// Команда
class TurnOn implements Command
{
    protected $bulb;
public function \_\_construct(Bulb $bulb)
{
    $this->bulb = $bulb;
}

public function execute()
{
    $this->bulb->turnOn();
}

public function undo()
{
    $this->bulb->turnOff();
}
    public function redo()
    {
        $this->execute();
    }
}
class TurnOff implements Command
{
    protected $bulb;
public function \_\_construct(Bulb $bulb)
{
    $this->bulb = $bulb;
}

public function execute()
{
    $this->bulb->turnOff();
}

public function undo()
{
    $this->bulb->turnOn();
}
    public function redo()
    {
        $this->execute();
    }
}
// Invoker
class RemoteControl
{
    public function submit(Command $command)
    {
        $command->execute();
    }
}

$bulb = new Bulb();

$turnOn = new TurnOn($bulb);
$turnOff = new TurnOff($bulb);

$remote = new RemoteControl();
$remote->submit($turnOn); // Лампочка загорелась!
$remote->submit($turnOff); // Темнота!

43
Q

Command - где может быть использован

A

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

44
Q

Iterator - это

A

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

45
Q

Iterator - пример

A
class RadioStation
{
    protected $frequency;
public function \_\_construct(float $frequency)
{
    $this->frequency = $frequency;
}
    public function getFrequency(): float
    {
        return $this->frequency;
    }
}

use Countable;
use Iterator;

class StationList implements Countable, Iterator
{
    /** @var RadioStation[] $stations */
    protected $stations = [];
    /** @var int $counter */
    protected $counter;
public function addStation(RadioStation $station)
{
    $this->stations[] = $station;
}

public function removeStation(RadioStation $toRemove)
{
    $toRemoveFrequency = $toRemove->getFrequency();
    $this->stations = array_filter($this->stations, function (RadioStation $station) use ($toRemoveFrequency) {
        return $station->getFrequency() !== $toRemoveFrequency;
    });
}
    public function count(): int
    {
        return count($this->stations);
    }
public function current(): RadioStation
{
    return $this->stations[$this->counter];
}

public function key()
{
    return $this->counter;
}

public function next()
{
    $this->counter++;
}

public function rewind()
{
    $this->counter = 0;
}
    public function valid(): bool
    {
        return isset($this->stations[$this->counter]);
    }
}

$stationList = new StationList();

// Добавление станций
$stationList->addStation(new RadioStation(89));
$stationList->addStation(new RadioStation(101));
$stationList->addStation(new RadioStation(102));
$stationList->addStation(new RadioStation(103.2));

foreach($stationList as $station) {
echo $station->getFrequency() . PHP_EOL;
}

$stationList->removeStation(new RadioStation(89)); // Удалит 89 станцию

46
Q

Mediator - это

A

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

47
Q

Mediator - пример

A

interface ChatRoomMediator
{
public function showMessage(User $user, string $message);
}

// Посредник
class ChatRoom implements ChatRoomMediator
{
    public function showMessage(User $user, string $message)
    {
        $time = date('M d, y H:i');
        $sender = $user->getName();
    echo $time . '[' . $sender . ']:' . $message;
} }

class User {
protected $name;
protected $chatMediator;

public function \_\_construct(string $name, ChatRoomMediator $chatMediator) {
    $this->name = $name;
    $this->chatMediator = $chatMediator;
}

public function getName() {
    return $this->name;
}

public function send($message) {
    $this->chatMediator->showMessage($this, $message);
} }

$mediator = new ChatRoom();

$john = new User('John Doe', $mediator);
$jane = new User('Jane Doe', $mediator);

$john->send(‘Привет!’);
$jane->send(‘Привет!’);

// Вывод
// Feb 14, 10:58 [John]: Привет!
// Feb 14, 10:58 [Jane]: Привет!
48
Q

Memento - это

A

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

49
Q

Memento - пример

A
class EditorMemento
{
    protected $content;
public function \_\_construct(string $content)
{
    $this->content = $content;
}
    public function getContent()
    {
        return $this->content;
    }
}
class Editor
{
    protected $content = '';
public function type(string $words)
{
    $this->content = $this->content . ' ' . $words;
}

public function getContent()
{
    return $this->content;
}
    public function save()
    {
        return new EditorMemento($this->content);
    }
public function restore(EditorMemento $memento)
{
    $this->content = $memento->getContent();
} }

$editor = new Editor();

// Печатаем что-нибудь
$editor->type('Это первое предложение.');
$editor->type('Это второе.');
// Сохраняем состояние для восстановления : Это первое предложение. Это второе.
$saved = $editor->save();
// Печатаем ещё
$editor->type('И это третье.');
// Вывод: Данные до сохранения
echo $editor->getContent(); // Это первое предложение. Это второе. И это третье.
// Восстановление последнего сохранения
$editor->restore($saved);

$editor->getContent(); // Это первое предложение. Это второе.

50
Q

Observer - это

A

поведенческий шаблон проектирования, также известен как «подчинённые» (Dependents). Создает механизм у класса, который позволяет получать экземпляру объекта этого класса оповещения от других объектов об изменении их состояния, тем самым наблюдая за ними.

51
Q

Observer - пример

A
class JobPost
{
    protected $title;
public function \_\_construct(string $title)
{
    $this->title = $title;
}
    public function getTitle()
    {
        return $this->title;
    }
}
class JobSeeker implements Observer
{
    protected $name;
public function \_\_construct(string $name)
{
    $this->name = $name;
}
    public function onJobPosted(JobPost $job)
    {
        // Делаем что-то с публикациями вакансий
        echo 'Привет ' . $this->name . '! Появилась новая работа: '. $job->getTitle();
    }
}
class JobPostings implements Observable
{
    protected $observers = [];
protected function notify(JobPost $jobPosting)
{
    foreach ($this->observers as $observer) {
        $observer->onJobPosted($jobPosting);
    }
}

public function attach(Observer $observer)
{
    $this->observers[] = $observer;
}
    public function addJob(JobPost $jobPosting)
    {
        $this->notify($jobPosting);
    }
}
// Создаем соискателей
$johnDoe = new JobSeeker('John Doe');
$janeDoe = new JobSeeker('Jane Doe');

// Создаем публикацию и добавляем подписчика
$jobPostings = new JobPostings();
$jobPostings->attach($johnDoe);
$jobPostings->attach($janeDoe);

// Добавляем новую работу и смотрим получит ли соискатель уведомление
$jobPostings->addJob(new JobPost('Software Engineer'));
// Вывод
// Привет John Doe! Появилась новая работа: Software Engineer
// Привет Jane Doe! Появилась новая работа: Software Engineer
52
Q

Visitor - это

A

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

53
Q

Visitor - пример

A
// Посещаемый
interface Animal
{
    public function accept(AnimalOperation $operation);
}
// Посетитель
interface AnimalOperation
{
    public function visitMonkey(Monkey $monkey);
    public function visitLion(Lion $lion);
    public function visitDolphin(Dolphin $dolphin);
}
class Monkey implements Animal
{
    public function shout()
    {
        echo 'У-у-а-а!';
    }
    public function accept(AnimalOperation $operation)
    {
        $operation->visitMonkey($this);
    }
}
class Lion implements Animal
{
    public function roar()
    {
        echo 'рррр!';
    }
    public function accept(AnimalOperation $operation)
    {
        $operation->visitLion($this);
    }
}
class Dolphin implements Animal
{
    public function speak()
    {
        echo '*звуки дельфина*!'; // Я понятия не имею как описать их звуки
    }
    public function accept(AnimalOperation $operation)
    {
        $operation->visitDolphin($this);
    }
}
class Speak implements AnimalOperation
{
    public function visitMonkey(Monkey $monkey)
    {
        $monkey->shout();
    }
public function visitLion(Lion $lion)
{
    $lion->roar();
}
    public function visitDolphin(Dolphin $dolphin)
    {
        $dolphin->speak();
    }
}
$monkey = new Monkey();
$lion = new Lion();
$dolphin = new Dolphin();

$speak = new Speak();

$monkey->accept($speak); // У-у-а-а!
$lion->accept($speak); // Рррр!
$dolphin->accept($speak); // звуки дельфина!

54
Q

Strategy - это

A

поведенческий шаблон проектирования, предназначенный для определения семейства алгоритмов, инкапсуляции каждого из них и обеспечения их взаимозаменяемости. Это позволяет выбирать алгоритм путём определения соответствующего класса. Шаблон Strategy позволяет менять выбранный алгоритм независимо от объектов-клиентов, которые его используют. Простыми словами: Шаблон стратегия позволяет переключаться между алгоритмами или стратегиями в зависимости от ситуации.

55
Q

Strategy - пример

A

interface SortStrategy
{
public function sort(array $dataset): array;
}

class BubbleSortStrategy implements SortStrategy
{
    public function sort(array $dataset): array
    {
        echo "Сортировка пузырьком";
        // Сортировка
        return $dataset;
    }
}
class QuickSortStrategy implements SortStrategy
{
    public function sort(array $dataset): array
    {
        echo "Быстрая сортировка";
        // Сортировка
        return $dataset;
    }
}
class Sorter
{
    protected $sorter;
public function \_\_construct(SortStrategy $sorter)
{
    $this->sorter = $sorter;
}

public function sort(array $dataset): array
{
    return $this->sorter->sort($dataset);
} }

$dataset = [1, 5, 4, 3, 2, 8];

$sorter = new Sorter(new BubbleSortStrategy());
$sorter->sort($dataset); // Вывод : Сортировка пузырьком
$sorter = new Sorter(new QuickSortStrategy());
$sorter->sort($dataset); // Вывод : Быстрая сортировка
56
Q

State - это

A

поведенческий шаблон проектирования. Используется в тех случаях, когда во время выполнения программы объект должен менять своё поведение в зависимости от своего состояния.

57
Q

State - пример

A

interface WritingState
{
public function write(string $words);
}

class UpperCase implements WritingState
{
    public function write(string $words)
    {
        echo strtoupper($words);
    }
}
class LowerCase implements WritingState
{
    public function write(string $words)
    {
        echo strtolower($words);
    }
}
class Default implements WritingState
{
    public function write(string $words)
    {
        echo $words;
    }
}
class TextEditor
{
    protected $state;
public function \_\_construct(WritingState $state)
{
    $this->state = $state;
}

public function setState(WritingState $state)
{
    $this->state = $state;
}
    public function type(string $words)
    {
        $this->state->write($words);
    }
}

$editor = new TextEditor(new Default());

$editor->type(‘Первая строка’);

$editor->setState(new UpperCase());

$editor->type(‘Вторая строка’);
$editor->type(‘Третья строка’);

$editor->setState(new LowerCase());

$editor->type(‘Четвертая строка’);
$editor->type(‘Пятая строка’);

// Output:
// Первая строка
// ВТОРАЯ СТРОКА
// ТРЕТЬЯ СТРОКА
// четвертая строка
// пятая строка
58
Q

Template method - это

A

поведенческий шаблон проектирования, определяющий основу алгоритма и позволяющий наследникам переопределять некоторые шаги алгоритма, не изменяя его структуру в целом. Простыми словами: Шаблонный метод определяет каркас выполнения определённого алгоритма, но реализацию самих этапов делегирует дочерним классам.

59
Q

Template method - пример

A
abstract class Builder
{
    // Шаблонный метод
    final public function build()
    {
        $this->test();
        $this->lint();
        $this->assemble();
        $this->deploy();
    }
    abstract public function test();
    abstract public function lint();
    abstract public function assemble();
    abstract public function deploy();
}
class AndroidBuilder extends Builder
{
    public function test()
    {
        echo 'Запуск Android тестов';
    }
public function lint()
{
    echo 'Копирование Android кода';
}

public function assemble()
{
    echo 'Android сборка';
}
    public function deploy()
    {
        echo 'Развертывание сборки на сервере';
    }
}
class IosBuilder extends Builder
{
    public function test()
    {
        echo 'Запуск iOS тестов';
    }
public function lint()
{
    echo 'Копирование iOS кода';
}

public function assemble()
{
    echo 'iOS сборка';
}
    public function deploy()
    {
        echo 'Развертывание сборки на сервере';
    }
}
$androidBuilder = new AndroidBuilder();
$androidBuilder->build();
// Вывод:
// Запуск Android тестов
// Копирование Android кода
// Android сборка
// Развертывание сборки на сервере
$iosBuilder = new IosBuilder();
$iosBuilder->build();
// Вывод:
// Запуск iOS тестов
// Копирование iOS кода
// iOS сборка
// Развертывание сборки на сервере