Раскройте шаблон псевдонима
12 мая 2022 г.Пока я пишу ООП-код, я применяю некоторые приемы Elegant Objects.
Один из них заключается в том, что классы должны быть окончательными. Это означает, что они не могут быть расширены за счет наследования, а только за счет композиции.
Преимущество в простоте. Я имею в виду, что таким образом каждый объект рассматривается как связный блок. Какой интерес для его клиентов является его открытое поведение. Ничего больше. Вместо этого через расширение клиент может сломать его.
Например, объект может связывать между собой два своих метода. Итак, если мы можем заменить через расширение один из них, мы можем сломать другой. По этой причине, чтобы быть уверенным, мы должны проверить его реализацию. Таким образом, мы увеличиваем связь между расширенным и расширением.
Другими словами, конечные классы навязывают идею о том, что мы должны заботиться только об открытом поведении. А не реализации. Тем не менее, это требует изменения того, как мы рассуждаем о них. Шаблон Alias упрощает один из аспектов этого изменения.
Намерение
Паттерн Alias позволяет расширить способ, которым класс может создавать свои объекты, не производя подклассов и не изменяя их.
Мотивация
Предположим, что конечный класс создает свои объекты, используя некоторые обязательные параметры. Как мы можем добавить еще один способ создания его объектов? Например, как мы можем добавить конструктор, который использует значение по умолчанию для одного или нескольких отсутствующих параметров?
Одним из подходов может быть добавление в класс еще одного конструктора. Но это может выйти из-под контроля. Более того, это может быть невозможно. Например, вышеупомянутый окончательный класс может находиться во внешней библиотеке.
Еще одним недостатком этого подхода является то, что мы можем загрязнить конечный класс. Например, у нас может быть окончательный класс, который строит свои объекты с учетом JSON. Но через некоторое время нам нужно добавить еще и XML. Как вы понимаете, добавление кода для сопоставления XML с JSON неизбежно загрязнит этот класс.
Однако шаблон Alias не ограничивается конечными классами. Например, у нас не может быть двух конструкторов с одинаковыми параметрами, но разной семантикой.
Чтобы решить эту проблему, мы можем добавить статические фабричные методы в код класса. Но те же вышеперечисленные недостатки сказываются и на этом подходе. То есть: это выходит из-под контроля; это не всегда возможно; это загрязнит класс.
Лучшим подходом к обеим проблемам является создание другого класса с желаемым поведением конструктора. Этот класс инкапсулирует собственную логику построения. И он делегирует все другому классу, включая фактическое создание. Это шаблон псевдонима.
Применимость
Используйте шаблон Alias, когда:
- Вам необходимо добавить или изменить конструктор конечного класса;
- Вы хотите добавить или изменить конструктор класса без изменения или создания подкласса;
- Вам нужны два или более конструктора класса с одинаковыми параметрами без изменения или создания подклассов.
Структура
Структура проста. Нам нужно как минимум два класса, реализующих один и тот же интерфейс: «Псевдоним» и «Псевдоним».
Участники
Интерфейс
- объявляет интерфейс.
Псевдоним
- реализует
АнИнтерфейс
;
- предоставляет один или несколько конструкторов.
Псевдоним
- реализует
АнИнтерфейс
;
- предоставляет один или несколько конструкторов;
- поддерживает ссылку на объект
Aliased
;
- делегирует все указанному объекту Aliased.
Сотрудничество
Псевдоним
строит - в соответствии со своими правилами - объектПсевдоним
и поддерживает ссылку на него. Затем он делегирует все псевдониму.
Последствия
Шаблон псевдонима имеет следующие последствия:
- Это позволяет легко добавлять или изменять конструкторы;
- Это способствует композиции вместо наследования;
- Увеличивает количество занятий;
- Это уменьшает дублирование кода при использовании для замены повторяющегося создания;
- Классы псевдонимов дублируют код делегирования. Если это проблема, ее можно решить с помощью базового абстрактного класса Alias.
Реализация
Для реализации паттерна Alias вам необходимо:
- определить интерфейс;
- реализовать ранее определенный интерфейс с классом. Это будет псевдоним;
- для реализации ранее определенного интерфейса с псевдонимом класса, и вам нужно:
- определить конструктор, который строит объект с псевдонимом в соответствии с некоторыми потребностями;
- частная переменная экземпляра, которая ссылается на ранее созданный объект с псевдонимом;
- делегировать все объекту с псевдонимом.
Образец кода
Приведенный ниже Java-код выражает шаблон псевдонима. В этом коде псевдоним вводит значение по умолчанию для обязательного параметра:
```java
интерфейс AnInterface {
аннулировать метод();
Что-то другоеMethod();
окончательный класс Aliased реализует AnInterface {
закрытый финал А а;
закрытый финал B b;
Псевдоним (конечный A a, конечный B b) {
это.а = а;
это.б = б;
недействительный метод () {
// реализация
Что-то другоеМетод() {
// реализация
окончательный класс Alias реализует AnInterface {
закрытый финал Псевдоним псевдоним;
Псевдоним (финал А а) {
это(
новый псевдоним(
а,
новый ЭкземплярB(...)
частный псевдоним (окончательный псевдоним) {
this.aliased = псевдоним;
недействительный метод () {
this.aliased.aMethod();
Что-то другоеМетод() {
вернуть this.aliased.anotherMethod();
Связанные шаблоны
В определенной степени паттерн Alias также можно рассматривать как способ [украсить] (https://en.wikipedia.org/wiki/Decorator_pattern) конструкцию объектов. Это видение особенно верно, если мы рассматриваем класс как объект, который отвечает за создание объектов.
Оригинал