|
|||||||
Декоратор
Время создания: 12.04.2018 12:19
Автор: br0ke
Текстовые метки: oop, design pattern, pattern, structural, decorator
Раздел: Информационные технологии - Паттерны проектирования (ООП) - Структурные
Запись: and-semakin/mytetra_data/master/base/1523517576wuli88avjr/text.html на raw.githubusercontent.com
|
|||||||
|
|||||||
Декоратор -- структурный паттерн, который позволяет динамически добавлять к объектам новую функциональность, оборачивая их в полезные "обертки". При этом для подключения дополнительной функциональности используется не сложная иерархия подклассов, что является классическим (и тупым) решением данной задачи, а отдельная иерархия декораторов. Каждый из видов дополнительной функциональности, которая может быть добавлена к объекту, помещается в отдельный класс. Эти классы сами по себе небольшие, поэтому в них легко разобраться. В паттерн "Декоратор" входят оборачиваемый объект и сама иерархия декораторов. Каждый из декораторов реализует какое-то одно функциональное свойство. Это позволяет соблюдать один из SOLID принципов -- принцип единственной ответственности. Так мы можем подключить к классу только ту функциональность, которая необходима ему в данный момент. Для подключения нескольких функциональных свойств можно последовательно использовать несколько декораторов. Структура декораторов Для создания паттерна "Декоратор" необходимы следующие классы:
Как видно из диаграммы, все декораторы по сути являются объектами, подобными самому компоненту. Из этого следует, что они реализуют одинаковый интерфейс. Согласно принципу подстановки Барбары Лисков у пользователя должна быть возможность корректного использования объекта-декоратора (то есть объекта, обернутого в декоратор), не зная об этом. Тут находится одно из слабых мест паттерна. Интерфейс объекта и интерфейс модифицированного объекта одинаковы. Это не всегда удобно, иногда для модифицированного объекта требуется отдельный интерфейс. Использование паттерна Декоратор При использовании паттерна декорируемый объект оборачивается в декоратор. Таким образом получается вложенная структура из декораторов. Отменить действие декоратора можно, если достать базовый объект из декоратора. Это можно сделать, обратившись к decorated_object.base. Аналогичным образом можно отменить эффект декоратора из середины иерархии. Для этого изменим базовый объект у внешнего декоратора на базовый объект декоратора, который необходимо удалить. Принцип похож на удаление элемента из середины односвязного списка. Пример использования Декоратора from abc import ABC, abstractmethod class Creature(ABC): @abstractmethod def feed(self): pass
@abstractmethod def move(self): pass
@abstractmethod def make_noise(self): pass
class Animal(Creature): def feed(self): print("I eat grass")
def move(self): print("I walk forward")
def make_noise(self): print("WOOO!")
class AbstractDecorator(Creature): def __init__(self, obj): self.obj = obj
def feed(self): self.obj.feed()
def move(self): self.obj.move()
def make_noise(self): self.obj.make_noise()
class Swimming(AbstractDecorator): def move(self): print("I swim")
def make_noise(self): print("...")
class Flying(AbstractDecorator): def move(self): print("I fly")
def make_noise(self): print("QUAAA!")
class Predator(AbstractDecorator): def feed(self): print("I eat other animals")
class Fast(AbstractDecorator): def move(self): self.obj.move() print("Fast!") animal = Animal() animal.feed() # I eat grass animal.move() # I walk forward animal.make_noise() # WOOO! print() animal = Swimming(animal) animal.feed() # I eat grass animal.move() # I swim animal.make_noise() # ... print() animal = Predator(animal) animal.feed() # I eat other animals animal.move() # I swim animal.make_noise() # ... print() animal = Fast(animal) animal.feed() # I eat other animals animal.move() # I swim Fast! animal.make_noise() # ... print() animal = Fast(animal) animal.feed() # I eat other animals animal.move() # I swim Fast! Fast! animal.make_noise() # ... print() |
|||||||
Прикрепленные файлы:
|
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|