Примеры шаблонов проектирования GoF в основных библиотеках Java
Я изучаю шаблоны проектирования GoF Java, и я хочу увидеть их примеры из жизни. Каковы некоторые хорошие примеры этих шаблонов проектирования в основных библиотеках Java?
7 ответов
Вы можете найти обзор многих шаблонов дизайна в Википедии. Также упоминается, какие шаблоны упоминаются GoF. Я суммирую их здесь и попытаюсь назначить как можно больше реализаций шаблонов, как в Java SE, так и в Java EE API.
Творческие образцы
Абстрактная фабрика (распознаваемая креативными методами, возвращающими саму фабрику, которая, в свою очередь, может использоваться для создания другого абстрактного / интерфейсного типа)
javax.xml.parsers.DocumentBuilderFactory#newInstance()
javax.xml.transform.TransformerFactory#newInstance()
javax.xml.xpath.XPathFactory#newInstance()
Builder (распознается креативными методами, возвращающими сам экземпляр)
java.lang.StringBuilder#append()
(Несинхронизированный)java.lang.StringBuffer#append()
(Синхронизированы)java.nio.ByteBuffer#put()
(также наCharBuffer
,ShortBuffer
,IntBuffer
,LongBuffer
,FloatBuffer
а такжеDoubleBuffer
)javax.swing.GroupLayout.Group#addComponent()
- Все реализации
java.lang.Appendable
java.util.stream.Stream.Builder
Фабричный метод (распознаваемый креативными методами, возвращающими реализацию абстрактного / интерфейсного типа)
java.util.Calendar#getInstance()
java.util.ResourceBundle#getBundle()
java.text.NumberFormat#getInstance()
java.nio.charset.Charset#forName()
java.net.URLStreamHandlerFactory#createURLStreamHandler(String)
(Возвращает одноэлементный объект по протоколу)java.util.EnumSet#of()
javax.xml.bind.JAXBContext#createMarshaller()
и другие подобные методы
Прототип (распознается креативными методами, возвращающими другой экземпляр самого себя с теми же свойствами)
java.lang.Object#clone()
(класс должен реализоватьjava.lang.Cloneable
)
Синглтон (распознаваемый креативными методами, возвращающими один и тот же экземпляр (обычно самого себя) каждый раз)
java.lang.Runtime#getRuntime()
java.awt.Desktop#getDesktop()
java.lang.System#getSecurityManager()
Структурные узоры
Адаптер (распознаваемый креативными методами, берущими экземпляр другого абстрактного / интерфейсного типа и возвращающий реализацию собственного / другого абстрактного / интерфейсного типа, который украшает / переопределяет данный экземпляр)
java.util.Arrays#asList()
java.util.Collections#list()
java.util.Collections#enumeration()
java.io.InputStreamReader(InputStream)
(возвращаетReader
)java.io.OutputStreamWriter(OutputStream)
(возвращаетWriter
)javax.xml.bind.annotation.adapters.XmlAdapter#marshal()
а также#unmarshal()
Мост (распознаваемый креативными методами, берущими экземпляр другого абстрактного / интерфейсного типа и возвращающий реализацию собственного абстрактного / интерфейсного типа, который делегирует / использует данный экземпляр)
- Никто еще не приходит на ум. Придуманный пример будет
new LinkedHashMap(LinkedHashSet<K>, List<V>)
которая возвращает неизменяемую связанную карту, которая не клонирует элементы, а использует их.java.util.Collections#newSetFromMap()
а такжеsingletonXXX()
методы, однако, приближается.
Составной (распознается поведенческими методами, берущими экземпляр одного и того же абстрактного / интерфейсного типа в древовидную структуру)
java.awt.Container#add(Component)
(практически на всем протяжении свинга)javax.faces.component.UIComponent#getChildren()
(практически во всем интерфейсе JSF)
Декоратор (распознается креативными методами, использующими экземпляр того же типа абстрактного / интерфейса, который добавляет дополнительное поведение)
- Все подклассы
java.io.InputStream
,OutputStream
,Reader
а такжеWriter
иметь конструктор, принимающий экземпляр того же типа. java.util.Collections
,checkedXXX()
,synchronizedXXX()
а такжеunmodifiableXXX()
методы.javax.servlet.http.HttpServletRequestWrapper
а такжеHttpServletResponseWrapper
javax.swing.JScrollPane
Фасад (распознается поведенческими методами, которые внутренне используют экземпляры различных независимых абстрактных / интерфейсных типов)
javax.faces.context.FacesContext
, он внутренне использует среди прочего абстрактные / интерфейсные типыLifeCycle
,ViewHandler
,NavigationHandler
и многое другое без того, что конечный пользователь должен беспокоиться об этом (которые, однако, могут быть переопределены путем инъекции).javax.faces.context.ExternalContext
, который внутренне используетServletContext
,HttpSession
,HttpServletRequest
,HttpServletResponse
, так далее.
Flyweight (распознается креативными методами, возвращающими кешированный экземпляр, немного "многотонная" идея)
java.lang.Integer#valueOf(int)
(также наBoolean
,Byte
,Character
,Short
,Long
а такжеBigDecimal
)
Прокси (распознаваемый креативными методами, который возвращает реализацию данного абстрактного / интерфейсного типа, который в свою очередь делегирует / использует другую реализацию данного абстрактного / интерфейсного типа)
java.lang.reflect.Proxy
java.rmi.*
javax.ejb.EJB
( объяснение здесь)javax.inject.Inject
( объяснение здесь)javax.persistence.PersistenceContext
Поведенческие модели
Цепочка ответственности (распознается поведенческими методами, которые (косвенно) вызывают тот же метод в другой реализации того же абстрактного / интерфейсного типа в очереди)
java.util.logging.Logger#log()
javax.servlet.Filter#doFilter()
Команда (распознаваемая поведенческими методами в абстрактном / интерфейсном типе, который вызывает метод в реализации другого абстрактного / интерфейсного типа, который был инкапсулирован реализацией команды во время ее создания)
- Все реализации
java.lang.Runnable
- Все реализации
javax.swing.Action
Интерпретатор (распознаваемый поведенческими методами, возвращающими структурно другой экземпляр / тип данного экземпляра / типа; обратите внимание, что синтаксический анализ / форматирование не является частью шаблона, определение шаблона и способ его применения)
java.util.Pattern
java.text.Normalizer
- Все подклассы
java.text.Format
- Все подклассы
javax.el.ELResolver
Итератор (распознается поведенческими методами, последовательно возвращая экземпляры другого типа из очереди)
- Все реализации
java.util.Iterator
(таким образом, среди других такжеjava.util.Scanner
!). - Все реализации
java.util.Enumeration
Посредник (распознаваемый поведенческими методами, берущими экземпляр другого абстрактного / интерфейсного типа (обычно использующий шаблон команды), который делегирует / использует данный экземпляр)
java.util.Timer
(всеscheduleXXX()
методы)java.util.concurrent.Executor#execute()
java.util.concurrent.ExecutorService
(invokeXXX()
а такжеsubmit()
методы)java.util.concurrent.ScheduledExecutorService
(всеscheduleXXX()
методы)java.lang.reflect.Method#invoke()
Памятка (распознаваемая поведенческими методами, которые внутренне изменяют состояние всего экземпляра)
java.util.Date
(методы сеттера делают это,Date
внутренне представленlong
значение)- Все реализации
java.io.Serializable
- Все реализации
javax.faces.component.StateHolder
Наблюдатель (или Публикация / подписка) (распознается поведенческими методами, которые вызывают метод в экземпляре другого абстрактного / интерфейсного типа, в зависимости от собственного состояния)
java.util.Observer
/java.util.Observable
(редко используется в реальном мире, хотя)- Все реализации
java.util.EventListener
(практически на всем протяжении свинга) javax.servlet.http.HttpSessionBindingListener
javax.servlet.http.HttpSessionAttributeListener
javax.faces.event.PhaseListener
Состояние (распознается поведенческими методами, которые изменяют свое поведение в зависимости от состояния экземпляра, которым можно управлять извне)
javax.faces.lifecycle.LifeCycle#execute()
(контролируетсяFacesServlet
поведение зависит от текущей фазы (состояния) жизненного цикла JSF)
Стратегия (распознается поведенческими методами в абстрактном / интерфейсном типе, который вызывает метод в реализации другого абстрактного / интерфейсного типа, который был передан в качестве аргумента метода в реализацию стратегии)
java.util.Comparator#compare()
, выполненный среди другихCollections#sort()
,javax.servlet.http.HttpServlet
,service()
и всеdoXXX()
методы принимаютHttpServletRequest
а такжеHttpServletResponse
и разработчик должен их обработать (а не завладеть ими как переменными экземпляра!).javax.servlet.Filter#doFilter()
Шаблонный метод (распознаваемый поведенческими методами, которые уже имеют поведение "по умолчанию", определенное абстрактным типом)
- Все неабстрактные методы
java.io.InputStream
,java.io.OutputStream
,java.io.Reader
а такжеjava.io.Writer
, - Все неабстрактные методы
java.util.AbstractList
,java.util.AbstractSet
а такжеjava.util.AbstractMap
, javax.servlet.http.HttpServlet
всеdoXXX()
method по умолчанию отправляет в ответ ошибку HTTP 405 "Method Not Allowed". Вы свободны, чтобы реализовать ни один или любой из них.
Посетитель (распознаваемый по двум разным абстрактным / интерфейсным типам, для которых определены методы, которые принимают друг друга от другого абстрактного / интерфейсного типа; один фактически вызывает метод другого, а другой выполняет для него требуемую стратегию)
javax.lang.model.element.AnnotationValue
а такжеAnnotationValueVisitor
javax.lang.model.element.Element
а такжеElementVisitor
javax.lang.model.type.TypeMirror
а такжеTypeVisitor
java.nio.file.FileVisitor
а такжеSimpleFileVisitor
javax.faces.component.visit.VisitContext
а такжеVisitCallback
- Схема наблюдателя на протяжении всего свинга (
Observable
,Observer
) - MVC также в разгаре
- Шаблон адаптера: InputStreamReader и OutputStreamWriter ПРИМЕЧАНИЕ.
ContainerAdapter
,ComponentAdapter
,FocusAdapter
,KeyAdapter
,MouseAdapter
не являются адаптерами; они на самом деле нулевые объекты. Плохой выбор имен от Sun. - Шаблон декоратора (
BufferedInputStream
может украсить другие потоки, такие какFilterInputStream
) - Шаблон AbstractFactory для AWT Toolkit и подключаемых классов Swing.
java.lang.Runtime#getRuntime()
СинглтонButtonGroup
для шаблона MediatorAction
,AbstractAction
может использоваться для разных визуальных представлений для выполнения одного и того же кода -> Шаблон команды- Interned Strings или CellRender в JTable for Flyweight Pattern (также подумайте о различных пулах - Пулы потоков, пулы соединений, пулы объектов EJB - Flyweight действительно об управлении общими ресурсами)
- Модель событий Java 1.0, как и фильтры сервлетов, является примером цепочки ответственности.
- Шаблон итератора в платформе коллекций
- Вложенные контейнеры в AWT/Swing используют шаблон Composite.
- Менеджеры по раскладке в AWT/Swing являются примером стратегии
и многое другое, я думаю,
- Flyweight используется с некоторыми значениями Byte, Short, Integer, Long и String.
- Фасад используется во многих местах, но наиболее очевидным является интерфейс сценариев.
- Синглтон - java.lang. Время приходит на ум.
- Абстрактная Фабрика - также Сценарии и JDBC API.
- Команда - Отменить / Повторить TextComponent.
- Интерпретатор - RegEx (java.util.regex.) И SQL (java.sql.) API.
- Прототип - Не уверен на 100%, если это рассчитывать, но я думаю,
clone()
метод может быть использован для этой цели.
RMI основан на Прокси.
Должна быть возможность процитировать один из 23 шаблонов в GoF:
- Абстрактная фабрика: все интерфейсы java.sql получают свои конкретные реализации из JDBC JAR при регистрации драйвера.
- Строитель: java.lang.StringBuilder.
- Фабрика Метод: фабрики XML, среди других.
- Прототип: Может быть, clone(), но я не уверен, что покупаю это.
- Синглтон: java.lang.System
- Адаптер: классы адаптера в java.awt.event, например, WindowAdapter.
- Мост: Коллекция классов в java.util. Список реализован ArrayList.
- Композитный: java.awt. java.awt.Component + java.awt.Container
- Декоратор: по всему пакету java.io.
- Фасад: ExternalContext ведет себя как фасад для выполнения файлов cookie, области сеанса и аналогичных операций.
- Flyweight: целое число, символ и т. Д.
- Прокси: пакет java.rmi
- Цепочка ответственности: фильтры сервлетов
- Команда: Swing пункты меню
- Интерпретатор: Нет напрямую в JDK, но JavaCC, безусловно, использует это.
- Iterator: интерфейс java.util.Iterator; не может быть яснее, чем это.
- Посредник: JMS?
- Memento:
- Наблюдатель: java.util.Observer/Observable (правда, плохо)
- Государственный:
- Стратегия:
- Шаблон:
- Посетитель:
Я не могу думать о примерах в Java для 10 из 23, но я посмотрю, смогу ли я добиться большего успеха завтра. Это то, что редактировать для.
Шаблон Абстрактная фабрика используется в разных местах. Например, DatagramSocketImplFactory
, PreferencesFactory
, Есть много других - поискать в Javadoc интерфейсы, в названии которых есть слово "Factory".
Также есть немало примеров фабричной модели.
java.util.Collection#Iterator является хорошим примером фабричного метода. В зависимости от конкретного подкласса Collection, который вы используете, он создаст реализацию Iterator. Поскольку и суперкласс Factory (Collection), и созданный Iterator являются интерфейсами, его иногда путают с AbstractFactory. Большинство примеров для AbstractFactory в принятом ответе (BalusC) являются примерами Factory, упрощенной версии Factory Method, которая не является частью оригинальных шаблонов GoF. В Facory иерархия классов Фабрики свернута, и фабрика использует другие средства для выбора продукта, который будет возвращен.
- Абстрактная Фабрика
Абстрактная фабрика имеет несколько фабричных методов, каждый из которых создает свой продукт. Продукты, произведенные на одном заводе, предназначены для совместного использования (ваш принтер и картриджи должны быть с одного (абстрактного) завода). Как упомянуто в ответах выше, семейства компонентов графического интерфейса пользователя AWT, отличающиеся от платформы к платформе, являются примером этого (хотя его реализация отличается от структуры, описанной в Gof).
Несмотря на то, что с этим часами у меня сломались часы, Java XML API часто использует Factory. Я имею в виду, просто посмотрите на это:
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(source);
String title = XPathFactory.newInstance().newXPath().evaluate("//title", doc);
...и так далее и тому подобное.
Кроме того, различные буферы (StringBuffer, ByteBuffer, StringBuilder) используют Builder.