Примеры шаблонов проектирования GoF в основных библиотеках Java
Я изучаю шаблоны проектирования GoF Java и хочу увидеть их реальные примеры. Назовите несколько хороших примеров этих шаблонов проектирования в основных библиотеках Java?
Переведено автоматически
Ответ 1
Вы можете найти обзор множества шаблонов проектирования в Википедии . Там также упоминается, какие шаблоны упоминаются GoF . Я подытожу их здесь и постараюсь назначить как можно больше реализаций шаблонов, найденных как в Java SE, так и в Java EE API.
Шаблоны создания
Абстрактная фабрика (распознается по методам создания, возвращающим саму фабрику, которая, в свою очередь, может быть использована для создания другого абстрактного типа интерфейса)
javax.xml.parsers.DocumentBuilderFactory#newInstance()
javax.xml.transform.TransformerFactory#newInstance()
javax.xml.xpath.XPathFactory#newInstance()
Конструктор (распознается по методам создания, возвращающим сам экземпляр)
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.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()
очень близки.
Composite (recognizeable by behavioral methods taking an instance of same abstract/interface type into a tree structure)
java.awt.Container#add(Component)
(practically all over Swing thus)javax.faces.component.UIComponent#getChildren()
(practically all over JSF UI thus)
Decorator (recognizeable by creational methods taking an instance of same abstract/interface type which adds additional behaviour)
- All subclasses of
java.io.InputStream
,OutputStream
,Reader
andWriter
have a constructor taking an instance of same type. java.util.Collections
, thecheckedXXX()
,synchronizedXXX()
andunmodifiableXXX()
methods.javax.servlet.http.HttpServletRequestWrapper
andHttpServletResponseWrapper
javax.swing.JScrollPane
Facade (recognizeable by behavioral methods which internally uses instances of different independent abstract/interface types)
javax.faces.context.FacesContext
, it internally uses among others the abstract/interface typesLifeCycle
,ViewHandler
,NavigationHandler
and many more without that the enduser has to worry about it (which are however overrideable by injection).javax.faces.context.ExternalContext
, which internally usesServletContext
,HttpSession
,HttpServletRequest
,HttpServletResponse
, etc.
Flyweight (recognizeable by creational methods returning a cached instance, a bit the "multiton" idea)
java.lang.Integer#valueOf(int)
(also onBoolean
,Byte
,Character
,Short
,Long
andBigDecimal
)
Proxy (recognizeable by creational methods which returns an implementation of given abstract/interface type which in turn delegates/uses a different implementation of given abstract/interface type)
java.lang.reflect.Proxy
java.rmi.*
javax.ejb.EJB
(explanation here)javax.inject.Inject
(explanation here)javax.persistence.PersistenceContext
Behavioral patterns
Chain of responsibility (recognizeable by behavioral methods which (indirectly) invokes the same method in another implementation of same abstract/interface type in a queue)
Command (recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of a different abstract/interface type which has been encapsulated by the command implementation during its creation)
- All implementations of
java.lang.Runnable
- All implementations of
javax.swing.Action
Interpreter (recognizeable by behavioral methods returning a structurally different instance/type of the given instance/type; note that parsing/formatting is not part of the pattern, determining the pattern and how to apply it is)
java.util.Pattern
java.text.Normalizer
- All subclasses of
java.text.Format
- All subclasses of
javax.el.ELResolver
Iterator (recognizeable by behavioral methods sequentially returning instances of a different type from a queue)
- All implementations of
java.util.Iterator
(thus among others alsojava.util.Scanner
!). - Все реализации
java.util.Enumeration
Посредник (распознаваемый поведенческими методами, использующими экземпляр другого абстрактного / интерфейсного типа (обычно с использованием шаблона command), который делегирует / использует данный экземпляр)
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()
Memento (распознается по поведенческим методам, которые внутренне изменяют состояние всего экземпляра)
java.util.Date
(это делают методы setter,Date
внутренне представленныеlong
значением)- Все реализации
java.io.Serializable
- Все реализации
javax.faces.component.StateHolder
Наблюдатель (или Публикация / Подписка) (распознается по поведенческим методам, которые вызывают метод в экземпляре другого абстрактного / интерфейсного типа, в зависимости от собственного состояния)
java.util.Observer
/java.util.Observable
(хотя и редко используется в реальном мире)- Все реализации
java.util.EventListener
(таким образом, практически все в Swing) 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()
и alldoXXX()
принимают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()
методы по умолчанию отправляют в ответ ошибку HTTP 405 "Метод не разрешен". Вы вольны не реализовать ни один из них.
Посетитель (распознается по двум разным абстрактным / интерфейсным типам, в которых определены методы, каждый из которых принимает другой абстрактный / интерфейсный тип; один фактически вызывает метод другого, а другой выполняет с ним желаемую стратегию)
Ответ 2
- Шаблон наблюдателя на протяжении всего swing (
Observable
,Observer
) - MVC также в swing
- Шаблон адаптера: InputStreamReader и OutputStreamWriter ПРИМЕЧАНИЕ:
ContainerAdapter
,ComponentAdapter
,FocusAdapter
KeyAdapter
,MouseAdapter
не являются адаптерами; на самом деле это нулевые объекты. Неудачный выбор имен Sun. - Шаблон декоратора (
BufferedInputStream
может украшать другие потоки, такие какFilterInputStream
) - Шаблон AbstractFactory для AWT Toolkit и подключаемых классов внешнего вида Swing
java.lang.Runtime#getRuntime()
является одноэлементнымButtonGroup
для шаблона посредникаAction
,AbstractAction
может использоваться для разных визуальных представлений для выполнения одного и того же кода -> Шаблон команды- Интернированные строки или CellRender в JTable для шаблона Flyweight (также подумайте о различных пулах - пулах потоков, пулах соединений, пулах объектов EJB - Flyweight на самом деле предназначен для управления общими ресурсами)
- Модель событий Java 1.0 является примером цепочки ответственности, как и фильтры сервлетов.
- Шаблон итератора в Collections Framework
- Вложенные контейнеры в AWT / Swing используют составной шаблон
- Менеджеры компоновки в AWT / Swing являются примером стратегии
и, я думаю, многое другое
Ответ 3
- Минимальный вес используется с некоторыми значениями Byte, Short, Integer, Long и String .
- Фасад используется во многих местах, но наиболее очевидным являются скриптовые интерфейсы.
- На ум приходитSingleton - java.lang.Runtime.
- Abstract Factory - Также скриптинг и JDBC API.
- Команда - отмена / повтор TextComponent.
- Интерпретатор - API регулярных выражений (java.util.regex.) и SQL (java.sql.).
- Прототип - Не уверен на 100%, учитывается ли это, но я думаю, что
clone()
метод можно использовать для этой цели.
Ответ 4
RMI основан на прокси.
Должна быть возможность привести один для большинства из 23 шаблонов в GoF:
- Абстрактная фабрика: все интерфейсы java.sql получают свои конкретные реализации из JDBC JAR при регистрации драйвера.
- Конструктор: java.lang.StringBuilder.
- Фабричный метод: XML-фабрики, среди прочего.
- Прототип: возможно, clone() , но я не уверен, что куплюсь на это.
- Singleton: java.язык.Система
- Адаптер: классы адаптеров в java.awt.event, например, WindowAdapter.
- Мост: коллекция классов в java.util. Список, реализованный ArrayList.
- Составной: java.awt. java.awt.Component + java.awt.Container
- Декоратор: по всему пакету java.io .
- Фасад: ExternalContext ведет себя как фасад для выполнения файлов cookie, области действия сеанса и аналогичных операций.
- Минимальный вес: целое число, символ и т.д.
- Прокси: пакет java.rmi
- Цепочка ответственности: фильтры сервлетов
- Команда: Пункты меню Swing
- Интерпретатор: Нет непосредственно в JDK, но JavaCC, безусловно, использует это.
- Итератор: java.util.Интерфейс итератора; яснее не скажешь.
- Посредник: JMS?
- Памятка:
- Observer: java.util.Observer / Observable (правда,сделано плохо)
- Состояние:
- СТРАТЕГИИ:
- Шаблон:
- Посетитель:
Я не могу вспомнить примеров в Java для 10 из 23, но я посмотрю, смогу ли я сделать лучше завтра. Для этого и существует edit.