ПРЕДИСЛОВИЕ
Почему мы написали эту книгу
За время своей преподавательской практики мы неоднократно сталкивались с тем, что большинство программистов-практиков, изучающих язык программирования Java, не могут четко объяснить, что такое шаблоны проектирования. Только один из десяти слушателей может припомнить название нескольких самых популярных шаблонов. С другой стороны, концепции, на которых основаны те или иные шаблоны проектирования, хорошо знакомы многим программистам, поскольку стоило нам продемонстрировать эти шаблоны на занятиях, как их тут же узнавали многие наши слушатели.
Поэтому мы решили создать нечто вроде каталога шаблонов проектирования для разработчиков, использующих язык программирования Java. Этот каталог, по нашему мнению, должен помочь, прежде всего тем разработчикам, которые хорошо понимают, какие преимущества дает применение шаблонов, и хотели бы работать с ними, но нуждаются в практическом руководстве, объясняющем, как и в каких случаях нужно применять тот или иной шаблон. Исходя из этого мы постарались написать книгу простым и понятным языком, а также привели полный текст всех рассмотренных в ней примеров, позволяющий получить полноценные работающие программы.
Мы будем считать, что справились с этой задачей, если вы, прочитав эту книгу, не только ознакомитесь с шаблонами проектирования и языком программирования Java, но и получите от нее удовольствие.
О чем эта книга
Эта книга призвана дать вам основные сведения, необходимые для практического применения шаблонов проектирования при разработке реальных Java-приложений. Кроме того, в этой книге показано, в каких случаях и почему следует отдавать предпочтение именно шаблонам проектирования, а не другим средствам API языка Java.
Для кого предназначена эта книга
Данная книга была написана прежде всего для опытных Java-программистов, которые желают изучить прогрессивные методы разработки приложений. Поэтому, приступая к чтению, вы должны хорошо знать язык программирования Java и иметь хотя бы базовые понятия об основных прикладных программных интерфейсах (API) этого языка. Также вам будут полезны знания базовых понятий UML, хотя для работы с книгой эти знания не являются обязательными. Мы можем порекомендовать книги Мартина Фаулера и Кендалла Скотта "UML в кратком изложении. Применение стандартного языка объектного моделирования" (М., Издательский дом научно-технической литературы "Мир", 1999. с. 192) или Крэга Лармана "Применение UML и шаблонов проектирования. Введение в объектно-ориентированный анализ и проектирование" (М., Издательский дом "Вильямс", 2001. с. 496).
Структура книги
Книга состоит из двух частей. Часть I, "Общеупотребительные шаблоны", по структуре подобна справочнику или каталогу шаблонов.
Глава 1, "Производящие шаблоны", посвящена описанию шаблонов, применяемых для создания объектов: Abstract Factory, Builder, Factory Method, Prototype и Singleton.
В главе 2, "Поведенческие шаблоны", рассматриваются шаблоны, которые позволяют определить поведение разрабатываемой объектной модели: Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method и Visitor.
В главе 3, "Структурные шаблоны", описаны шаблоны, с помощью которых можно структурировать приложения: Adapter, Bridge, Composite, Decorator, Facade, Flyweight, HOPP и Proxy.
В главе 4, "Системные шаблоны", представлены шаблоны, помогающие получить улучшенные архитектурные решения: Callback, Router, MVC, Session, Successive Update, Transaction и Worker Thread.
Часть II, "Шаблоны в языке программирования Java", содержит основные сведения о программных интерфейсах (API) Java (глава 5), а также о том, какие преимущества дает программисту использование шаблонов, рассматриваемых API.
В главе 6, "Основные API языка Java", приведен обзор основных API, таких как API обработки событий, JavaBeans, AWT, Swing, коллекций, ввода/вывода и динамической подгрузки классов во время выполнения.
Глава 7, "Технологии распределенной обработки данных", посвящена описанию некоторых API распределенной обработки данных и особенностям применения шаблонов таких API, как JNDI, JDBC, RMI и CORBA.
Глава 8, "Архитектуры Jini и J2EE", содержит информацию о двух дополнительных библиотеках Jini и J2EE. В частности, в данной главе рассмотрены такие технологии J2EE, как сервлеты, JSP и EJB.
Как пользоваться этой книгой
Можно, конечно, прочесть эту книгу от начала до конца, не пропуская ни одной страницы. Однако мы рекомендуем начать с простых шаблонов (Factory Method, Singleton, Observer и Composite), а затем уже продолжить изучение остального материала. Другой подход заключается в том, чтобы сразу перейти к чтению материала второй части, если какой-то из описанных в ней API хорошо вам знаком, чтобы на примере этого API быстрее понять, как нужно использовать шаблоны.
Описания шаблонов можно изучать в любом порядке. Мы постарались расположить материал так, чтобы впоследствии вы могли обращаться к нему, как к справочнику, когда у вас возникнет необходимость освежить знания в процессе применения шаблонов на практике.
Web-узел, посвященный данной книге
Специально для этой книги мы разработали Web-узел, на котором размещаем обновленную информацию и другие материалы. Адрес узла: http://www.phptr.com/ applied-javapatterns.
Благодарности
Любая книга представляет собой, конечно же, плод коллективных усилий. Мы хотели бы поблагодарить всех, кто воплотил эту книгу в жизнь. Нам посчастливилось работать с чудесными людьми, и мы решили посвятить эту страницу им, чтобы они знали, как мы ценим их вклад в общее дело.
Грэгу Дончу (Greg Doench), провидцу из издательства Prentice Hall. Спасибо вам за то, что вы были "великим кормчим" этого проекта. Приступив к работе, мы выяснили, что Грэг увлекается марафоном. Когда Стив намекнул, что он хотел бы попробовать свои силы в этом виде спорта, Грэг ответил: "Не раньше, чем закончим книгу". Теперь мы понимаем, почему он так сказал: написание книги очень похоже на марафонский забег. Примите нашу искреннюю благодарность за вашу постоянную помощь и поддержку и за вашу веру в успех этого проекта.
Рашель Борден (Rachel Borden), светилу Sun Press. Спасибо вам за руководство проектом на всем его протяжении, вплоть до публикации книги. Если бы не вы, мы бы растеряли все свои идеи в тех листках, которыми были облеплены наши рабочие места. Спасибо вам за постоянную поддержку и внимание, а также за терпение, которое вы проявляли, растолковывая технарям тонкости издательского дела. Отдельная благодарность за то, что вы нередко вставали спозаранку, чтобы провести телеконференцию с людьми, находящимися на другой стороне Земного шара. Но больше всего мы благодарим вас за то, что в нашей работе вы всегда были лидером, задающим темп.
Сольвейг Хогланд (Solveig Haugland), выдающемуся редактору. Спасибо вам за то, что поверили в мечту, и за то, что помогли превратить ее в реальность. Спасибо вам за то, что шли до конца и превратили груду бессвязных идей в нечто гораздо более значимое. Наконец, спасибо вам за то, что показали нам, что даже в технической книге можно найти место для юмора.
Нашим талантливым техническим рецензентам. Спасибо за то, что заставили нас как следует думать о том, что мы намереваемся сказать. Наша самая искренняя благодарность Дженни Йип (Jennie Yip) за потраченное ею время, когда она тщательно описывала все найденные в тексте неточности, а также Брайну Бэшаму (Brayan Basham), Берту Бейтсу (Bert Bates), Джону Крапи (John Crupi), Джиму Голлентайну (Jim Gallentine), Вернеру ван Муку (Werner van Mook), Нанно Скерингу (Nanno Schering), Юргену Скимбера (Juergen Schimbera), Роберту Скрайджверсу (Robert Schrijvers) и Фреду Зюйдендорпу (Zuijdendorp).
Выражаем сердечную благодарность сотрудникам издательства Prentice Hall. Мы искренне просим извинить нас за то, что не смогли встретиться со всеми вами лично, но знаем, что именно вы превращаете идеи авторов в реальные книги. Ваша работа поистине прекрасна - вы помогаете принести в мир мечты и идеи. Мы благодарим вас за вашу преданность работе как над этой, так и над другими книгами (многие из которых заняли подобающее им место и в наших сердцах, и на наших книжных полках).
Стефен Стелтинг хотел бы поблагодарить Стива Брэдшоу (Steve Bradshaw), Аннет Балденегро (Annette Baldenegro), Синди Льюис (Cindy Lewis) и других менеджеров Sun Educational Services. Спасибо за вашу поддержку и за веру в нас, которые вы демонстрировали на протяжении последнего года. Ваши помощь и понимание так дороги для нас, что слишком трудно выразить это словами.
Олаф Маассен благодарит своих менеджеров Гарри Поландта (Harry Pallandt) и Андрэ Арнольдаса (Andre Arnoldus) за возможность часто оставаться на работе по окончании рабочего дня, а также за поддержку на протяжении многих лет.
Ингрид и Нильс - вы две самые большие звезды в моей вселенной. Спасибо вам за поддержку и вдохновение, благодаря которым я закончил этот проект.
Брит - ты моя третья "звездочка". Благодарю тебя за то, что не спешил появляться на свет, пока я не закончу книгу. Теперь я могу всецело заняться следующим большим проектом - моей семьей.
ВВЕДЕНИЕ
Почему шаблоны?
Если бы строители строили дома так, как программисты пишут программный код, достаточно было бы одного-единственного дятла, чтобы разрушить всю цивилизацию.
Если бы вы решили построить дом, как бы вы это делали?
Можно к этой работе подойти так, как некоторые и поступают, когда собираются построить скворечник.
1. Найти подходящее дерево.
2. Приготовить доски, молоток и гвозди.
3. Взобраться на дерево, применить материалы и инструменты, перечисленные в п. 2.
4. Спуститься и надеяться, что все обойдется.
Конечно, любой, кто хоть раз пытался действовать подобным образом, знает, что результат, скорее всего, будет плачевным - в некоторых случаях гибнет не только скворечник, но и дерево. Более правильный подход состоит в том, чтобы найти мастера и попросить его помочь в подготовке чертежей. Если же вы собираетесь построить не скворечник, а настоящий дом, большинство здравомыслящих людей обратиться за помощью к архитектору.
Однако на основе чего архитектор, будучи экспертом по строительству домов, принимает те или иные решения? Возможно ли, располагая многолетним опытом, применить его для строительства совершенно нового, нетипичного дома? Повидимому, есть нечто, основанное на знаниях, опыте и, возможно, в некоторой степени на интуиции, что позволяет архитектору достичь успеха.
Вопросы, связанные со строительством и проектированием зданий, в действительности не очень отличаются от тех, с которыми мы сталкиваемся в мире разработки программного обеспечения (ПО). Каким образом спроектировать по-настоящему хорошую программу? Как применить опыт прошлых лет к проектам, нацеленным на будущее? На основе чего нужно принимать решения при проектировании программы, которые позволили бы получить продукт, обладающий хорошими показателями, такими как гибкость, расширяемость и эффективность?
Как и при строительстве зданий, нам нужен опытный руководитель, который будет играть роль архитектора. Знания, опыт и здравый смысл так же нужны при проектировании ПО, как и при проектировании домов. Иными словами, нам нужен гуру в области разработки ПО.
Однако в мире не так уж много гуру. И до тех пор, пока технология клонирования не получила всеобщего одобрения, нам чаще всего придется рассчитывать на свои силы. Нам придется растить экспертов по разработке ПО в ходе выполнения своих проектов, отбирая потенциальных кандидатов среди сотрудников своих компаний.
Итак, все вернулось на круги своя. Мы хотим спроектировать хорошее ПО, но не знаем при этом, какие архитектурные решения будут правильными, позволяющими нам получить качественный продукт. Мы хотим вырастить опытных разработчиков ПО, но даже не представляем, как собрать воедино знания об эффективном проектировании, накопленные современными разработчиками ПО.
Может быть, существует способ собрать эти знания? Может быть, мы можем приобщиться к опыту гуру? Как нам записать и обобщить ключевые концепции проектирования ПО, положив тем самым фундамент для нового поколения разработчиков?
Да, решение проблемы существует и имя ему "шаблоны проектирования".
Они хорошо документированы, поэтому эксперты часто без труда справляются с новыми проблемами, просто применяя решения, которые уже работали в подобных ситуациях в прошлом. Сначала эксперты вычленяют составные части проблемы, требующей решения, которые подобны задачам, возникавшим перед ними в прошлом. Затем они вспоминают, какие решения применялись в прошлый раз, и обобщают эти решения. Наконец, эксперты адаптируют общее решение к контексту частной проблемы.
Идея, на которой основывается применение шаблонов проектирования, заключается в том, чтобы выработать стандартизованный подход к представлению общих решений, пригодных для часто встречающихся ситуаций при разработке ПО. Такой подход имеет ряд преимуществ.
- Со временем можно получить каталог шаблонов. Это позволяет новичкам в разработке ПО более эффективно использовать многолетний опыт их предшественников.
- Все решения, принимаемые при проектировании ПО, снабжены формализованным описанием, позволяющим оценить как достоинства, так и недостатки того или иного решения. Стандартизованные шаблоны облегчают как для новичков, так и для экспертов в области разработки ПО понимание того, как влияют на архитектуру создаваемой программы те или иные решения.
- Шаблоны проектирования позволяют всем, кто их использует, "говорить на одном языке". Это, в свою очередь, облегчает взаимопонимание между разработчиками при выборе того или иного решения. Вместо того чтобы детально описывать какое-либо архитектурное решение, мы говорим, какой шаблон мы намерены использовать.
- Мы можем соотносить шаблоны друг с другом, что позволяет разработчику увидеть, какие шаблоны могут использоваться в одном проекте.
Шаблоны проектирования предоставляют в наше распоряжение эффективный способ делиться опытом со всеми участниками сообщества объектно-ориентированного программирования. Независимо от того, каким языком программирования мы владеем (C++, Smalltalk или Java), и того, в какой области мы приобрели опыт проектирования ПО (Web-проекты, интеграция устаревших систем или заказной проект), мы можем накапливать свой собственный опыт и делиться им с другими разработчиками. Если же говорить о долгосрочной перспективе, то данный подход позволяет улучшить состояние дел во всей индустрии разработки ПО.
История применения шаблонов
Они прибыли из иных миров: из Университета Калифорнии в Беркли
Идейным отцом применения шаблонов проектирования при разработке ПО считают профессора архитектуры Университета Калифорнии в Беркли Кристофера Алегсандера (Christofer Alexander). В конце 70-х годов прошлого века он опубликовал несколько книг, в которых изложил основные принципы применения шаблонов в архитектуре, а также поместил каталог архитектурных шаблонов.
Именно посвященные шаблонам работы Алегсандера и привлекли внимание к проблеме программистов, интересующихся объектно-ориентированным программированием (ООП). В их среде появились пионеры применения шаблонов в разработке ПО, которые на протяжении последующих десяти лет сформулировали основные принципы этого метода. Среди первопроходцев были Кент Бэк (Kent Beck) и Уард Каннингхэм (Ward Cunningham). В 1987 году на конференции OOPSLA (Object-Oriented Programming, Systems, and Applications), посвященной ООП, прозвучал их доклад о применении шаблонов проектирования в языке Smalltalk. Еще одним адептом нового подхода стал Джеймс Коплайен (James Coplien), который в начале 90-х гг написал книгу о применении идиом (т.е. шаблонов) при разработке ПО на языке C++.
Ежегодные конференции OOPSLA сослужили хорошую службу для роста сторонников технологии шаблонов, так как на ее мероприятиях энтузиасты могли свободно делиться своими идеями со множеством благодарных слушателей. Кроме того, важную роль в становлении данного направления технологии разработки ПО сыграли конференции некоммерческой организации Hillside Group, создателями которой были Кент Бэк и Гради Буч (Grady Booch).
Однако по-настоящему ощутимый вклад в дело популяризации технологии шаблонов проектирования внесла изданная в 1995 году книга Design Patterns: Elements of Reusable Object-Oriented Software.
Ее авторы Эрик Гамма (Erich Gamma), Ричард Хелм (Richard Helm), Ральф Джонсон (Ralph Johnson) и Джон Влиссидес (John Vlissides) приложили так много усилий для распространения своих идей, что заслужили шутливое прозвище "Четверка" (GoF - gang of four). В книге представлено введение в довольно сложный язык шаблонов с иллюстрациями реализации обсуждаемых шаблонов на языке C++. Среди прочих книг, существенно повлиявших на развитие технологии шаблонов, можно отметить работу Френка Баскмана (Frank Buschmann), Регины Менье (Regine Meunier), Ханса Ронерта (Hans Rohnert) и Майкла Стала (Michael Stal) под названием Pattern-Oriented Software Architecture, A System of Patterns.
Выход в свет этих двух книг о шаблонах проектирования привлек внимание к технологии шаблонов и вызвал интерес в самых широких программистских кругах.
В это же время началось бурное развитие технологии Java, поэтому неудивительно, что Java-разработчики с самого начала стали применять шаблоны проектирования в своих проектах. Рост популярности технологии шаблонов проектирования среди Java-разработчиков проявился как в виде специальных презентаций на конференциях, таких как JavaOne, так и в появлении отдельной рубрики по шаблонам проектирования практически во всех специализированных журналах по программированию на Java.
Основные концепции технологии шаблонов
Поговорим о том, о сем...
В центре технологии шаблонов лежит идея стандартизации информации о типичной проблеме и о методах ее решения. Один из самых полезных результатов, полученных в работе Алегсандера, состоит в выделении некоторого способа представления шаблонов, который впоследствии был назван формой (form), или форматом (format). В форме Алегсандера применялось пять направлений, по которым формализовалось обсуждение шаблонов и их применение в конкретных ситуациях.
Самое главное преимущество такого подхода состоит в том, что даже само название шаблона представляет собой ответ на вопрос: "Что можно сделать с помощью этого шаблона?" Кроме того, в форме содержится: описание проблемной области; пояснение того, как данный шаблон решает означенную проблему; в чем заключаются преимущества, недостатки и, возможно, компромиссы при использовании данного шаблона.
Естественно, когда шаблоны были восприняты миром ООП, появились вариации формы Алегсандера, призванные учитывать интересы разработчиков ПО. Большинство из существующих сегодня форм были построены на одной или двух формах, получивших название "Канонических", или форм "Четверки". В данной книге используется одна из вариаций форм "Четверки", согласно которой при представлении шаблонов освещаются следующие вопросы.
- Название (Name). Слово или выражение, описывающее основное назначение шаблона.
- Также известен как (Also Known As). Альтернативные названия (если, конечно, таковые имеются).
- Свойства шаблона (Pattern Properties). Классификация шаблона. Мы будем определять шаблон, используя термины из двух следующих групп.
Тип:
- Производящие шаблоны (Creational patterns), предназначенные для создания объектов.
- Поведенческие шаблоны (Behavioral patterns), обеспечивающие координацию функционального взаимодействия между объектами.
- Структурные шаблоны (Structural patterns), используемые для управления статическими, структурными связями между объектами.
- Системные шаблоны (System patterns), предназначенные для управления взаимодействием на системном уровне.
Уровень:
- Отдельный класс (single class). Шаблон применяется к отдельному, независимому классу.
- Компонент (component). Шаблон используется для создания группы классов.
- Архитектурный (architectural). Шаблон используется для координации работы систем и подсистем.
- Назначение (Purpose). Короткое описание назначения шаблона.
- Представление (Introduction). Описание типичной проблемы, для решения которой можно использовать данный шаблон, подкрепленное примером.
- Область применения (Applicability). Определение ситуаций, в которых можно использовать данный шаблон проектирования.
- Описание (Description). Более подробное обсуждение логики работы и поведения шаблона.
- Реализация (Implementation). Описание того, что нужно сделать при реализации данного шаблона. Если вы решили, что этот шаблон вам подходит, в данном разделе вы найдете сведения о том, как практически реализовать программный код, построенный на его основе.
- Достоинства и недостатки (Benefits and Drawbacks). Что вам даст использование данного шаблона и чем, возможно, придется пожертвовать.
- Варианты (Pattern Variants). Возможные варианты реализации и (или) самого шаблона.
- Родственные шаблоны (Related Patterns). Описание других шаблонов, которые близки по назначению с рассматриваемым шаблоном или каким-то образом связаны с ним.
- Пример (Example). Пример использования шаблона в программе, написанной на языке Java.
Повторное использование и абстракция программного кода или :закончу и начну сначала...
Технология шаблонов проектирования стала важным эволюционным этапом в развитии таких концепций, как абстракция (abstraction) и повторное использование (reuse) программного кода. Обе эти концепции занимают центральное место в самой идее программирования (некоторые даже полагают, что они являются важнейшими концепциями).
Абстракция - это метод, с помощью которого разработчики могут решать сложные проблемы, последовательно разбивая их на более простые. Затем можно использовать имеющиеся готовые решения полученных типовых простых проблем в качестве строительных блоков, из которых разработчики получают решения, пригодные для реализации повседневных сложных проектов.
Повторное использование не менее важно для разработки ПО. Можно без преувеличения сказать, что вся история разработки ПО отмечена постоянным поиском все более и более изощренных методов повторного использования программного кода. В чем же тут дело? Зачем все это нужно? Оказывается, что повторное использование - это, по сути, цель, к которой устремлена технология разработки ПО по своей природе. Представим, например, что нужно создать в условиях жестких временных ограничений крупный программный проект. Какой путь вы бы выбрали?
- Написать весь код "с нуля", заставив и себя, и всех окружающих пройти через длительный и болезненный процесс тестирования и проверки всего написанного кода.
- Использовать проверенный и протестированный код в качестве фундамента своего проекта.
Поймите меня правильно: я прекрасно знаю, что кодирование - это тяжкий труд. Это тестирование, отладка, документирование и послепродажное сопровождение, т.е. все то, что так в большинстве своем не любят разработчики. Поэтому мы и придумали несколько методов повторного использования кода и концепций разработки ПО.
- Раньше других появился метод повторного использования, основанный на технологии "скопируй и вставь", или, проще говоря, на вставке в новые программы фрагментов ранее созданных программ. Об эффективности такого, с позволения сказать, повторного использования, лучше умолчать. Кроме того, данный метод также не дает никаких сколько-нибудь заметных качественных преимуществ с точки зрения абстракции кода.
- Более гибкий метод повторного использования состоит в повторном использовании алгоритмов. В соответствии с этим методом, разработчик может использовать любой однажды разработанный алгоритм, например такой, как алгоритм сортировки или поиска, для того, чтобы абстрагировать подход (обычно, основанный на математических выкладках) к решению вычислительных задач определенного класса.
- Функциональное повторное использование программного кода, а также его "идеологический противник" - повторное использование структур данных, позволяют обеспечить непосредственное повторное использование абстракции кода. Например, любой разработчик, задавшийся целью смоделировать нечто наподобие адреса, может определить структуру, содержащую все необходимые поля, а затем применять повторное использование этой структуры во всех проектах, требующих работы с адресами. Подобным же образом можно определить операцию по начислению налогов в виде функции (процедуры, подпрограммы, метода - в зависимости от выбранного языка программирования) computeTax, а затем копировать ее в каждый новый проект.
Двумя расширениями концепции повторного использования кода являются библиотеки функций и API. Они представляют разработчику возможность получить полный пакет функциональности, доступный для всех последующих приложений без необходимости копирования программного кода из приложения в приложение.
В ходе развития объектно-ориентированных языков программирования был совершен огромный скачок вперед в области абстракции и повторного использования программного кода. С помощью этой технологии была создана целая плеяда высокопроизводительных методов его создания.
Например, чего стоит только одна концепция класса как "эталона" объектов, с ее объединением двух ранее возникших механизмов: функциональной абстракции и абстракции данных. Объединяя структуру сущности (данные) с функциональностью, которая применяется к сущности (поведение), мы получаем эффективный метод повторного использования программного элемента.
Помимо основополагающего понятия класса, объектно-ориентированные языки принесли с собой множество других методов использования существующего кода.
В качестве примера можно привести такие концепции, как концепции подклассов и интерфейсов, открывших совершенно новые возможности в повторном использовании программного кода при разработке ПО. Наконец, можно вспомнить о таком мощном механизме, как ассоциация друг с другом групп классов, после чего эти группы рассматриваются как единый логический программный компонент, что обеспечивает возможность получения очень мощной с точки повторного использования модели на системном уровне.
Одной из самых выдающихся возможностей, предоставляемых шаблонами проектирования, является то, что они позволяют разработчикам более эффективно применять другие методы повторного использования программного кода. Шаблон в определенных ситуациях может, например, использоваться как руководство для эффективного управления наследованием или же для эффективного назначения связей между классами, обеспечивая тем самым решение той или иной проблемы.
Резюме
Шаблоны проектирования - это весьма ценное инструментальное средство в арсенале разработчика ПО, позволяющее существенно повысить эффективность создаваемого кода. В данной книге представлены лишь некоторые из самых популярных шаблонов проектирования, хотя на самом деле их гораздо больше. Добро пожаловать в мир шаблонов проектирования!