На собеседованиях очень часто спрашивают о шаблонах проектирования. Даже если вы использовали их каждый день, сложно быстро вспомнить и рассказать своими словами, чем они друг от друга отличаются. Воспользуемся таким приемом мнемотехники, как смешные и нелепые картинки и ассоциации с всем явлениями из реальной жизни, чтобы понимать суть шаблона проектирования.
На самом деле, большинство программистов и так, конечно, знает основные шаблоны проектирования, поэтому это скорее просто, чтобы быстро вспомнить на собеседовании.
Осторожно: пятничный пост (да — в понедельник, но вот такая вот у меня пятницо :) ), под катом смешные и нелепые картинки.
Паттерны проектирования (они же, Design pattern, они же, шаблоны проектирования, они же Жора, они же Гоша… ) — это набор "рецептов" по построению приложения. Причем "рецептов" достаточно общих.
Давайте рассмотрим их подробнее на аналогах из реального мира (чтобы упростить запоминания для ответов).
I. Порождающие шаблоны
Шаблоны проектирования, которые абстрагируют процесс инстанцирования. Они позволяют сделать систему независимой от способа создания, композиции и представления объектов. Шаблон, порождающий классы, использует наследование, чтобы изменять инстанцируемый класс, а шаблон, порождающий объекты, делегирует инстанцирование другому объекту. (с) Википедия
Проще говоря, это шаблоны для создания других классов.
1) Абстрактная фабрика (Abstract factory).
Аналог — различные вендинговые машины
Представим, что нам требуется разработать сеть разных аппаратов по продаже шоколадок, кофе, печенек. Мы создаем проект некоторого абстрактного аппарата (который может выдавать шоколадок, кофе и печенки). Это будет абстрактная фабрика и абстрактные продукты.
На основе его делаем проекты большого количества реальных аппаратов, которые выдают конкретные виды продуктов. Это реальные фабрики унаследованные от абстрактной.
Они могут выглядеть так:
Или так:
Но созданы на основе одного и того же проекта абстрактного аппарата.
Предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов.
Плюсы:
- изолирует конкретные классы;
- упрощает замену семейств продуктов;
- гарантирует сочетаемость продуктов.
Минусы:
- Добавить новый вид продукта достаточно сложно
public interface IButton {
void paint();
}
public interface IGUIFactory {
public IButton createButton();
}
public class WinFactory implements IGUIFactory {
Override
public IButton createButton() {
return new WinButton();
}
}
public class OSXFactory implements IGUIFactory {
Override
public IButton createButton() {
return new OSXButton();
}
}
public class WinButton implements IButton {
Override
public void paint() {
System.out.println("WinButton");
}
}
public class OSXButton implements IButton {
Override
public void paint() {
System.out.println("OSXButton");
}
}
public class Main {
public static void main(final String[] arguments) throws Exception {
IGUIFactory factory = null;
final String appearance = randomAppearance(); // Current operating system
if (appearance.equals("OSX")) {
factory = new OSXFactory();
} else if(appearance.equals("Windows")) {
factory = new WinFactory();
} else {
throw new Exception("No such operating system");
}
final IButton button = factory.createButton();
button.paint();
}
/**
* This is just for the sake of testing this program, and doesn't have to do
* with Abstract Factory pattern.
* @return
*/
public static String randomAppearance() {
final String[] appearanceArray = new String[3];
appearanceArray[0] = "OSX";
appearanceArray[1] = "Windows";
appearanceArray[2] = "error";
final java.util.Random random = new java.util.Random();
final int randomNumber = random.nextInt(3);
return appearanceArray[randomNumber];
}
}
2) Строитель (Builder).
Класс, который представляет собой интерфейс для создания сложного объекта. (с) вики
Аналог:
… заказ в пиццерии с возможностью выбора компонентов. Вы сами выбираете как создать вашу пиццу из заданных компонент. Сам билдер это повар, а результат его работы — полученный продукт (объект)
А если серьезнее:
3) Прототип (Prototype).
Определяет интерфейс создания объекта через клонирование другого объекта вместо создания через конструктор. (с) вики
Аналог:
… обычный ксерокс. Вы можете сделать копию документа (объекта), вместо того чтобы создавать его с нуля.
Если серьезнее
Вики
4) Одиночка (Singleton)
Класс, который может иметь только один экземпляр. (с) вики
Аналоги:
… должность президента страны, должность генерального директора фирмы и т.п.
Президент у страны может быть только один, хотя люди на этой должности меняются, но в одно и тоже время двух президентов быть не может, так же одиночка всегда должна иметь только одну реализацию.
II. Структурные шаблоны
1) Адаптер (Adapter / Wrapper)
Объект, обеспечивающий взаимодействие двух других объектов, один из которых использует, а другой предоставляет несовместимый с первым интерфейс. © Вики
Аналог:
… синхронный переводчик. Позволяет понимать друг друга самым разным людям (и классам)
2) Компоновщик (Composite pattern)
Объект, который объединяет в себе объекты, подобные ему самому. Компоновщик позволяет клиентам обращаться к отдельным объектам и к группам объектов одинаково. © Вики
Аналог в реальном мире:
… сержанты, офицеры в армии. Достаточно дать приказ только одному офицеру (сержанту), чтобы целая рота отправилась его выполнять. При этом сам офицер (сержант) такой же военный как и все остальные.
3) Шаблон фасад (Facade)
Структурный шаблон проектирования, позволяющий скрыть сложность системы путём сведения всех возможных внешних вызовов к одному объекту, делегирующему их соответствующим объектам системы. © Вики
Аналог:
… прораб на строительстве. Заказчику не обязательно пытаться управлять каждым рабочим на стройке, достаточно объяснить что именно нужно сделать прорабу.
4) Заместитель (Proxy)
Proxy — структурный шаблон проектирования, который предоставляет объект, который контролирует доступ к другому объекту, перехватывая все вызовы (выполняет функцию контейнера) © Вики
Аналог в реальном мире:
… секретарь у директора. Отфильтровывает неважные звонки и посетителей, если они не достаточно важны. При необходимости перенаправляя запросы реальному объекту (директору).
6) Приспособленец (Flyweight)
Приспособленец — структурный шаблон проектирования, при котором объект, представляющий себя как уникальный экземпляр в разных местах программы, по факту не является таковым. © Вики
Аналог в реальном мире:
… например, индивидуальный предприниматель, который сам себе начисляет зарплату, сам работает и грузчиком и продавцом, сам себя отпускает в отпуск, как директор.
7) Декоратор (Decorator)
структурный шаблон проектирования, предназначенный для динамического подключения дополнительного поведения к объекту.
Аналог в реальном мире:
Шпион… то есть разведчик, например такой:
С одной стороны, на первый взгляд, обычный сотрудник, но на самом деле, с функцией хмм… логирования и нотификации важной информации.
На данный момент это только первая часть, где лишь половина шаблонов проектирования, если статья будет интересна, напишу вторую часть.