|
Design
patterns
В математике давно выработаны общие
методы решения типовых задач. Доказательство теоремы начинается со слов: "Проведем
доказательство от противного" или: "Докажем это методом математической
индукции", и вы сразу представляете себе схему доказательства, его путь
становится вам понятен.
Нет ли подобных общих методов в
программировании? Есть.
Допустим, вам поручили автоматизировать
метеорологическую станцию. Информация от различных датчиков или, другими словами,
контроллеров
температуры, давления, влажности, скорости ветра поступает
в цифровом виде в компьютер. Там она обрабатывается: вычисляются усредненные
значения по регионам, на основе многодневных наблюдений делается прогноз на
завтра, т. е. создается
модель
метеорологической картины местности. Затем
прогноз выводится по разным каналам: на экран монитора, самописец, передается
по сети. Он представляется в разных
видах,
колонках чисел, графиках,
диаграммах.
Естественно спроектировать такую
автоматизированную систему из трех частей.
-
Первая часть, назовем ее
Контроллером
(controller), принимает сведения от датчиков и преобразует их в какую-то
единообразную форму, пригодную для дальнейшей обработки, например, приводит
к одному масштабу. При этом для каждого датчика надо написать свой модуль,
на вход которого поступают сигналы конкретного устройства, а на выходе образуется
унифицированная информация.
-
Вторая часть, назовем ее
Моделью
(model), принимает эту унифицированную информацию от Контроллера,
ничего не зная о датчике и не интересуясь тем, от какого именно датчика она
поступила, и преобразует ее по своим алгоритмам опять-таки к какому-то однообразному
виду, например, к последовательности чисел.
-
Третья часть системы,
Вид
(view),
непосредственно связана с устройствами вывода и преобразует поступившую от
Модели последовательность чисел в график, диаграмму или пакет для отправки
по сети. Для каждого устройства придется написать свой модуль, учитывающий
особенности именно этого устройства.
В чем удобство такой трехзвенной
схемы? Она очень гибка. Замена одного датчика приведет к замене только одного
модуля в Контроллере, ни Модель, ни Вид этого даже не заметят. Надо представить
прогноз в каком-то новом виде, например, для телевидения? Пожалуйста, достаточно
написать один модуль и вставить его в Вид. Изменился алгоритм обработки данных?
Меняем Модель.
Эта схема разработана еще в 80-х
годах прошлого столетия [То есть
XX
века. —
Ред.
] в языке Smalltalk
и получила название MVG (Model-View-Controller). Оказалось, что она применима
во многих областях, далеких от метеорологии, всюду, где удобно отделить обработку
от ввода и вывода информации.
Сбор информации часто организуется
так. На экране дисплея открывается поле ввода, в которое вы набиваете сведения,
допустим, фамилии в произвольном порядке, а в соседнем поле вывода отображается
обработанная информация, например, список фамилий по алфавиту. Будьте уверены,
что эта программа организована по схеме МУС. Контроллером служит поле ввода,
Видом — поле вывода, а Моделью — метод сортировки фамилий. В третьей части книги
мы рассмотрим примеры реализации этой схемы.
К середине 90-х годов накопилось
много подобных схем. В них сконцентрирован многолетний опыт тысяч программистов,
выражены наилучшие решения типовых задач.
Вот, пожалуй, самая простая из этих
схем. Надо написать класс, у которого можно создать только один экземпляр, но
этим экземпляром должны пользоваться объекты других классов. Для решения этой
задачи предложена схема Singleton, представленная в листинге 3.5.
Листинг 3.5.
Схема Singleton
final
class Singleton{
private
static Singleton s = new Singleton(0);
private
int k;
private
Singleton(int i){k = i;}
public
static Singleton getReference()(return s;}
public
int getValue(){return k;}
public
void setValue(int i){k = i;}
}
public class SingletonTest
{
public
static void main(String[] args){
Singleton ref = Singleton.getReference();
System.out.println(ref.getValue());
ref.setValue(ref.getValue() + 5);
System.out.println(ref.getValue());
}
}
Класс
singleton
окончательный — его нельзя расширить. Его конструктор закрытый — никакой метод
не может создать экземпляр этого класса. Единственный экземпляр
s
класса
singleton
— статический, он создается
внутри класса. Зато любой объект может получить ссылку на экземпляр методом
getReference ()
, Изменить состояние экземпляра s методом
s
etValue()
или просмотреть его текущее состояние методом
getValue()
.
Это только схема — класс
singleton
надо еще наполнить полезным содержимым, но идея выражена ясно
и полностью.
Схемы проектирования были систематизированы
и изложены в книге [7]. Четыре автора этой книги были прозваны "бандой
четырех" (Gang of Four), а книга, коротко, "GoF". Схемы обработки
информации получили название "Design Patterns". Русский термин еще
не устоялся. Говорят о "шаблонах", "схемах разработки",
"шаблонах проектирования".
В книге GoF описаны 23 шаблона,
разбитые на три группы:
1. Шаблоны создания объектов: Factory,
Abstract Factory, Singleton, Builder, Prototype.
2. Шаблоны структуры объектов: Adapter,
Bridge, Composite, Decorator, Facade, Flyweight, Proxy.
3. Шаблоны поведения объектов: Chain
of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer,
State, Strategy, Template, Visitor.
Описания даны, в основном, на языке
C++. В книге [8] те же шаблоны представлены на языке Java. Той же теме посвящено
электронное издание [9]. В книге [10] подробно обсуждаются вопросы разработки
систем на основе design patterns.
Мы, к сожалению, не можем разобрать
подробно design patterns в этой кни-те. Но каждый программист начала XXI века
должен их знать. Описание многих разработок начинается словами: "Проект
решен на основе шаблона", и структура проекта сразу становится ясна для
всякого, знакомого с design patterns.
По ходу книги мы будем указывать,
на основе какого шаблона сделана та или иная разработка.
|