Шаблон делегирования | Delegation pattern | Объект внешне выражает некоторое поведение, но в реальности передаёт ответственность за выполнение этого поведения связанному объекту. | |
Шаблон функционального дизайна | Functional design | Гарантирует, что каждый модуль компьютерной программы имеет только одну обязанность и исполняет её с минимумом побочных эффектов на другие части программы. | |
Неизменяемый интерфейс | Immutable interface | Создание неизменяемого объекта. | |
Интерфейс | Interface | Общий метод для структурирования компьютерных программ для того, чтобы их было проще понять. | |
Интерфейс-маркер | Marker interface | В качестве атрибута (как пометки объектной сущности) применяется наличие или отсутствие реализации интерфейса-маркера. В современных языках программирования вместо этого могут применяться атрибуты или аннотации. | |
Контейнер свойств | Property container | Позволяет добавлять дополнительные свойства для класса в контейнер (внутри класса), вместо расширения класса новыми свойствами. | |
Канал событий | Event channel | Создает централизованный канал для событий. Использует объект-представитель для подписки и объект-представитель для публикации события в канале. Представитель существует отдельно от реального издателя или подписчика. Подписчик может получать опубликованные события от более чем одного объекта, даже если он зарегистрирован только на одном канале. |
Шаблон делегирования
В этом шаблоне проектирования объект внешне выражает некоторое поведение, но в реальности передаёт ответственность за выполнение этого поведения связанному объекту. Шаблон делегирования является фундаментальной абстракцией, на основе которой реализованы другие шаблоны - композиция (также называемая агрегацией), примеси (mixins) и аспекты (aspects).
Пример на PHP
class A { public function f() { print "А: Вызываем метод f()"; } public function g() { print "А: Вызываем метод g()"; } } class C { private $_a; public function __construct() { $this->_a = new A; } public function f() { $this->_a->f(); } public function g() { $this->_a->g(); } public function y() { print "C: вызываем метод y()"; } } $obj = new C; $obj->f(); $obj->g(); $obj->y();
Пример на Python
#python 3 class A: def f(self): print('A : вызываем метод f') def g(self): print('A : вызываем метод g') class C: def __init__(self): self.A = A() def f(self): return self.A.f() def g(self): return self.A.g() c = C() c.f() #A: вызываем метод f c.g() #A: вызываем метод g
Шаблон функционального дизайна
Этот шаблон должен использоваться во всех программах. Но это, скорее, идеал - к этому надо стремиться, но достигнуть очень сложно. Каждая часть программы должна делать только то, для чего предназначена, и минимально влиять на другие части программы. То есть, если вывод на экран и запрос в базу происходит в одном и том же месте - это ошибка. Такой код стоило сразу разбить на маленькие кусочки. Обеспечить такой дизайн достаточно просто - надо к каждой функции приписывать комментарий, что она делает. Если в описании будет слово "и" или "или" ("эта функция стирает носки и готовит кофе"), значит, стоить разбить ее на две функции ("эта функция стирает носки", "эта функция готовит кофе").
Неизменяемый интерфейс
Неизменяемый интерфейс включает в себя определение типа, который не предоставляет никаких методов, которые могут изменить состояние. Объекты, на которые ссылается этот тип, выглядят как неизменяемые.
Пример на Java. Рассмотрим класс java, который представляет собой двухмерную точку.
public class Point2D { private int x; private int y; public Point2D(int x, int y) { this.x = x; this.y = y; } public int getX() { return this.x; } public int getY() { return this.y; } public void setX(int newX) { this.x = newX; } public void setY(int newY) { this.y = newY; } }
Класс Point2D является изменяемым: его состояние может быть изменено после создания, если вызвать один из методов-сеттеров (setX() или setY()). Неизменяемый интерфейс для Point2D может быть определен как:
public interface ImmutablePoint2D { public int getX(); public int getY(); }
Сделав Point2D реализующим ImmutablePoint2D, код клиента теперь может использовать тип, который не имеет изменяющих методов, и, таким образом, остается неизменяемым. Это демонстрируется в следующем примере:
ImmutablePoint2D point = new Point2D(0,0); // на конкретный экземпляр Point2D ссылается неизменяемый интерфейс int х = point.getX(); // допустимый вызов метода point.setX(42); // ошибка компиляции: метод setX() не существует в типе ImmutablePoint2D
Интерфейс
Интерфейс является общим способом для структурирования программ для того, чтобы их было проще понять. В общем, интерфейс — это класс, который обеспечивает программисту простой или более программно-специфический способ доступа к другим классам.
Интерфейс в PHP. Обхявление интерфейса осуществляется с помощью ключевого слова interface:
interface iTemplate { public function setVariable($name, $var); public function getHtml($template); }
Реализация интефрейса через имплемент:
class Template implements iTemplate { private $vars = array(); public function setVariable($name, $var) { $this->vars[$name] = $var; } public function getHtml($template) { foreach($this->vars as $name => $value) { $template = str_replace('{' . $name . '}', $value, $template); } return $template; } }
Интерфейсы могут быть унаследованы друг от друга, так же, как и классы, с помощью оператора extends.
Интерфейс в Java. Объявление:
interface Printable{ void print(); }
Все методы интерфейса не имеют модификаторов доступа, но фактически по умолчанию доступ public, так как цель интерфейса - определение функционала для реализации его классом. Поэтому весь функционал должен быть открыт для реализации.
Реализация:
class Book implements Printable{ public void print() { System.out.printf("%s (%s) \n", name, author); } }
Стоит также отметить следующее. Такие языки, как PHP и Java не поддерживают множественного наследования. Однако, благодаря интерфейсам и механизму внедрения зависимостей, можно осуществить имитацию множественного наследования.
Интерфейс-маркер
Данный шаблон предоставляет возможность связать интерфейс с классом даже при отсутствии в языке явной поддержки для метаданных.
В отличие от обычного интерфейса, который определяет функциональность (в виде объявлений методов и свойств), которой должен обладать реализуемый класс объектов, важен сам факт обладания класса маркером. Маркер лишь является признаком наличия определённого поведения у объектов класса, помеченного маркером.
Контейнер свойств
Контейнер свойств служит для обеспечения возможности уже построенного и развернутого приложения.
Классическим примером использованием шаблона является приложение, используемое для хранения и классификации информации. Например, приложение заказа фильмов. При разработке класса, представляющего фильм, при разработке и запуске приложения невозможно предусмотреть все возможные свойства (атрибуты), описывающие фильм. Поэтому класс фильма при необходимости в любой момент может быть расширен дополнительными свойствами. Для этого требуются предусмотреть механизм расширения свойств перед выпуском приложения.
Канал событий
Канал событий используется для создания канала связи и коммуникации через него посредством событий. Этот канал обеспечивает возможность разным издателям публиковать события и подписчикам, подписываясь на них, получать уведомления.
Шаблон Канал событий использует сильно типизированные события; это означает, что подписчик может ожидать поступления определенных типов данных события, если регистрируется для определенного события. Он также позволяет подписчику отправлять события, а не только получать события, посланные ему.