Инструменты пользователя

Инструменты сайта


php:shablony_proektirovanija:structural_patterns:decorator

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
php:shablony_proektirovanija:structural_patterns:decorator [2023/08/17 13:53]
werwolf
php:shablony_proektirovanija:structural_patterns:decorator [2023/08/17 13:58] (текущий)
werwolf
Строка 1: Строка 1:
-<​code>## ​Декоратор (Decorator)+===== Декоратор (Decorator) ​=====
  
-[▶ code](http://​webmastermsk.ru:​30000/​serg/​patterns-php/​-/​blob/​main/​structural/​Decorator.php)+[[http://​webmastermsk.ru:​30000/​serg/​patterns-php/​-/​blob/​main/​structural/​Decorator.php|▶ code]]
  
 > Шаблон декоратора позволяет динамически изменять поведение объекта во время выполнения,​ заключая его в объект класса > Шаблон декоратора позволяет динамически изменять поведение объекта во время выполнения,​ заключая его в объект класса
-декоратора.+декоратора.
  
-Возможность динамически добавлять новые обязанности,​ не прибегая к порождению подклассов,​ облегчает понимание основных+Возможность динамически добавлять новые обязанности,​ не прибегая к порождению подклассов,​ облегчает понимание основных\\ 
 обязанностей объектов и не запутывает основную бизнес-логику информационных систем. обязанностей объектов и не запутывает основную бизнес-логику информационных систем.
  
-Можно добавлять и удалять обязанности во время выполнения программы,​ в то время как при использовании наследования надо+Можно добавлять и удалять обязанности во время выполнения программы,​ в то время как при использовании наследования надо\\ 
 было бы создавать новый класс для каждой дополнительной обязанности. было бы создавать новый класс для каждой дополнительной обязанности.
  
-Данный шаблон позволяет не создавать классов,​ перегруженных методами. Новые обязанности можно добавлять только по мере+Данный шаблон позволяет не создавать классов,​ перегруженных методами. Новые обязанности можно добавлять только по мере\\ 
 необходимости,​ не перегружая программное обеспечение лишними классами. необходимости,​ не перегружая программное обеспечение лишними классами.
  
 **Использование:​** **Использование:​**
  
-Когда вам нужно добавлять обязанности объектам на лету, незаметно для кода, который их использует. +  * Когда вам нужно добавлять обязанности объектам на лету, незаметно для кода, который их использует. 
-    ​Объекты помещают в обёртки,​ имеющие дополнительные поведения. Обёртки и сами объекты имеют одинаковый интерфейс,​ +    ​Объекты помещают в обёртки,​ имеющие дополнительные поведения. Обёртки и сами объекты имеют одинаковый интерфейс,​\\  
-   ​поэтому клиентам без разницы,​ с чем работать – с обычным объектом данных или с обёрнутым. +поэтому клиентам без разницы,​ с чем работать – с обычным объектом данных или с обёрнутым. 
-Когда нельзя расширить обязанности объекта с помощью наследования. +  ​* ​Когда нельзя расширить обязанности объекта с помощью наследования. 
-    ​Во многих языках программирования есть ключевое слово final, которое может заблокировать наследование класса. +    ​Во многих языках программирования есть ключевое слово final, которое может заблокировать наследование класса.\\  
-      Расширить такие классы можно только с помощью Декоратора.+Расширить такие классы можно только с помощью Декоратора.
  
 **Преимущества:​** **Преимущества:​**
  
-Большая гибкость,​ чем у наследования. +  * Большая гибкость,​ чем у наследования. 
-Позволяет добавлять обязанности на лету. +  ​* ​Позволяет добавлять обязанности на лету. 
-Можно добавлять несколько новых обязанностей сразу. +  ​* ​Можно добавлять несколько новых обязанностей сразу. 
-Позволяет иметь несколько мелких объектов вместо одного объекта на все случаи жизни.+  ​* ​Позволяет иметь несколько мелких объектов вместо одного объекта на все случаи жизни.
  
 **Недостатки:​** **Недостатки:​**
  
-Трудно конфигурировать многократно обёрнутые объекты. +  * Трудно конфигурировать многократно обёрнутые объекты. 
-Обилие крошечных классов.+  ​* ​Обилие крошечных классов.
  
-<​details>​ 
-<​summary><​strong>​Связи с другими паттернами</​strong></​summary>​ 
-<br> 
-Адаптер меняет интерфейс существующего объекта. Декоратор улучшает другой объект без изменения его интерфейса. Причём 
-Декоратор поддерживает рекурсивную вложенность,​ чего не скажешь об Адаптере.<​br>​ 
-<br> 
-Адаптер предоставляет классу альтернативный интерфейс. Декоратор предоставляет расширенный интерфейс. Заместитель 
-предоставляет тот же интерфейс.<​br>​ 
-<br> 
-Цепочка обязанностей и Декоратор имеют очень похожие структуры. Оба паттерна базируются на принципе рекурсивного 
-выполнения операции через серию связанных объектов. Но есть и несколько важных отличий.<​br>​ 
-<br> 
-Обработчики в Цепочке обязанностей могут выполнять произвольные действия,​ независимые друг от друга, а также в любой 
-момент прерывать дальнейшую передачу по цепочке. С другой стороны Декораторы расширяют какое-то определённое действие,​ 
-не ломая интерфейс базовой операции и не прерывая выполнение остальных декораторов.<​br>​ 
-<br> 
-Компоновщик и Декоратор имеют похожие структуры классов из-за того, что оба построены на рекурсивной вложенности. Она 
-позволяет связать в одну структуру бесконечное количество объектов.<​br>​ 
-<br> 
-Декоратор оборачивает только один объект,​ а узел Компоновщика может иметь много детей. Декоратор добавляет вложенному 
-объекту новую функциональность,​ а Компоновщик не добавляет ничего нового,​ но «суммирует» результаты всех своих детей.<​br>​ 
-<br> 
-Но они могут и сотрудничать:​ Компоновщик может использовать Декоратор,​ чтобы переопределить функции отдельных частей 
-дерева компонентов.<​br>​ 
-<br> 
-Архитектура,​ построенная на Компоновщиках и Декораторах,​ часто может быть улучшена за счёт внедрения Прототипа. Он 
-позволяет клонировать сложные структуры объектов,​ а не собирать их заново.<​br>​ 
-<br> 
-Стратегия меняет поведение объекта «изнутри»,​ а Декоратор изменяет его «снаружи».<​br>​ 
-<br> 
-Декоратор и Заместитель имеют схожие структуры,​ но разные назначения. Они похожи тем, что оба построены на принципе 
-композиции и делегируют работу другим объектам. Паттерны отличаются тем, что Заместитель сам управляет жизнью сервисного 
-объекта,​ а обёртывание Декораторов контролируется клиентом.<​br>​ 
-<br> 
-</​details>​ 
  
 +**Связи с другими паттернами**
 +
 +Адаптер меняет интерфейс существующего объекта. Декоратор улучшает другой объект без изменения его интерфейса. Причём\\ ​
 +Декоратор поддерживает рекурсивную вложенность,​ чего не скажешь об Адаптере.
 +
 +Адаптер предоставляет классу альтернативный интерфейс. Декоратор предоставляет расширенный интерфейс. Заместитель\\ ​
 +предоставляет тот же интерфейс.
 +
 +Цепочка обязанностей и Декоратор имеют очень похожие структуры. Оба паттерна базируются на принципе рекурсивного\\ ​
 +выполнения операции через серию связанных объектов. Но есть и несколько важных отличий.
 +
 +Обработчики в Цепочке обязанностей могут выполнять произвольные действия,​ независимые друг от друга, а также в любой\\ ​
 +момент прерывать дальнейшую передачу по цепочке. С другой стороны Декораторы расширяют какое-то определённое действие,​\\ ​
 +не ломая интерфейс базовой операции и не прерывая выполнение остальных декораторов.
 +
 +Компоновщик и Декоратор имеют похожие структуры классов из-за того, что оба построены на рекурсивной вложенности. Она\\ ​
 +позволяет связать в одну структуру бесконечное количество объектов.
 +
 +Декоратор оборачивает только один объект,​ а узел Компоновщика может иметь много детей. Декоратор добавляет вложенному\\ ​
 +объекту новую функциональность,​ а Компоновщик не добавляет ничего нового,​ но «суммирует» результаты всех своих детей.
 +
 +Но они могут и сотрудничать:​ Компоновщик может использовать Декоратор,​ чтобы переопределить функции отдельных частей\\ ​
 +дерева компонентов.
 +
 +Архитектура,​ построенная на Компоновщиках и Декораторах,​ часто может быть улучшена за счёт внедрения Прототипа. Он\\ ​
 +позволяет клонировать сложные структуры объектов,​ а не собирать их заново.
 +
 +Стратегия меняет поведение объекта «изнутри»,​ а Декоратор изменяет его «снаружи».
 +
 +Декоратор и Заместитель имеют схожие структуры,​ но разные назначения. Они похожи тем, что оба построены на принципе\\ ​
 +композиции и делегируют работу другим объектам. Паттерны отличаются тем, что Заместитель сам управляет жизнью сервисного\\ ​
 +объекта,​ а обёртывание Декораторов контролируется клиентом.
 +
 +
 +<code php>
 +
 +<?php
 +
 +interface Worker
 +{
 +    public function countSalary():​ int;
 +}
 +
 +abstract class WorkerDecorator implements Worker
 +{
 +    public Worker $worker;
 +
 +    public function __construct(Worker $worker)
 +    {
 +        $this->​worker = $worker;
 +    }
 +}
 +
 +class Developer implements Worker
 +{
 +    public function countSalary():​ int
 +    {
 +        return 20 * 3000;
 +    }
 +}
 +
 +class DeveloperOverTime extends WorkerDecorator
 +{
 +    public function countSalary():​ int
 +    {
 +        return $this->​worker->​countSalary() + $this->​worker->​countSalary() * 0.2;
 +    }
 +}
 +
 +$developer = new Developer();​
 +$developerOverTime = new DeveloperOverTime($developer);​
 +
 +echo $developer->​countSalary();​ // 60000
 +echo $developerOverTime->​countSalary();​ // 72000
 +
 +// ----------- 2 -----------
 +
 +interface Coffee
 +{
 +    public function getCost();
 +
 +    public function getDescription();​
 +}
 +
 +class SimpleCoffee implements Coffee
 +{
 +    public function getCost()
 +    {
 +        return 10;
 +    }
 +
 +    public function getDescription()
 +    {
 +        return '​Simple coffee';​
 +    }
 +}
 +
 +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() . ', milk';
 +    }
 +}
 +
 +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() . ', whip';
 +    }
 +}
 +
 +$someCoffee = new SimpleCoffee();​
 +echo $someCoffee->​getCost();​ // 10
 +echo $someCoffee->​getDescription();​ // Simple Coffee
 +
 +$someCoffee = new MilkCoffee($someCoffee);​
 +echo $someCoffee->​getCost();​ // 12
 +echo $someCoffee->​getDescription();​ // Simple Coffee, milk
 +
 +$someCoffee = new WhipCoffee($someCoffee);​
 +echo $someCoffee->​getCost();​ // 17
 +echo $someCoffee->​getDescription();​ // Simple Coffee, milk, whip
 +
 +
 +// ----------- 3 -----------
 +
 +interface Booking
 +{
 +    public function calculatePrice():​ int;
 +
 +    public function getDescription():​ string;
 +}
 +
 +// Шаблон "​Декоратор"​ хранит ссылку на объект (компонент),​ определяет его интерфейс и переадресует на него рабочие запросы.
 +abstract class BookingDecorator implements Booking
 +{
 +    public function __construct(protected Booking $booking)
 +    {
 +    }
 +}
 +
 +// Системный компонент определяет интерфейс объекта,​ на который могут быть динамически возложены дополнительные обязанности
 +class DoubleRoomBooking implements Booking
 +{
 +    public function calculatePrice():​ int
 +    {
 +        return 40;
 +    }
 +
 +    public function getDescription():​ string
 +    {
 +        return '​double room';
 +    }
 +}
 +
 +// Конкретный компонент определяет объект,​ на который возлагаются дополнительные обязанности.
 +class ExtraBed extends BookingDecorator
 +{
 +    private const PRICE = 30;
 +
 +    public function calculatePrice():​ int
 +    {
 +        return $this->​booking->​calculatePrice() + self::​PRICE;​
 +    }
 +
 +    public function getDescription():​ string
 +    {
 +        return $this->​booking->​getDescription() . ' with extra bed';
 +    }
 +}
 +
 +class WiFi extends BookingDecorator
 +{
 +    private const PRICE = 2;
 +
 +    public function calculatePrice():​ int
 +    {
 +        return $this->​booking->​calculatePrice() + self::​PRICE;​
 +    }
 +
 +    public function getDescription():​ string
 +    {
 +        return $this->​booking->​getDescription() . ' with wifi';
 +    }
 +}
 +
 +$booking = new DoubleRoomBooking();​
 +
 +echo $booking->​calculatePrice();​ // 4
 +echo $booking->​getDescription();​ // double room
 +
 +$booking2 = new DoubleRoomBooking();​
 +$booking2 = new WiFi($booking2);​
 +
 +echo $booking2->​calculatePrice();​ // 42
 +echo $booking2->​getDescription();​ // double room with wifi
 +
 +$booking3 = new DoubleRoomBooking();​
 +$booking3 = new WiFi($booking);​
 +$booking3 = new ExtraBed($booking);​
 +
 +echo $booking3->​calculatePrice();​ // 72
 +echo $booking3->​getDescription();​ // double room with wifi with extra bed
 </​code>​ </​code>​
  
php/shablony_proektirovanija/structural_patterns/decorator.1692269596.txt.gz · Последние изменения: 2023/08/17 13:53 — werwolf