Я изучаю шаблоны проектирования Java GoF, и я хочу увидеть некоторые примеры реальной жизни. Каковы некоторые хорошие примеры этих шаблонов проектирования в основных библиотеках Java?
Примеры шаблонов проектирования GoF в основных библиотеках Java
Ответ 1
Вы можете найти обзор многих шаблонов дизайна в Википедии. Также упоминается, какие шаблоны упоминаются 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.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)
(таким образом, практически во всем Swing) -
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
и многие другие без того, чтобыViewHandler
беспокоиться об этом (которые, однако, могут быть переопределены инъекцией). -
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.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
(практически во всем 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()
и все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()
по умолчанию отправляют в ответ ошибку HTTP 405 "Метод не разрешен". Вы свободны, чтобы реализовать ни один или любой из них.
Посетитель (распознаваемый по двум разным типам абстрактных/интерфейсов, в которых определены методы, каждый из которых принимает другой тип абстрактных/интерфейсных: один фактически вызывает метод другого, а другой выполняет для него требуемую стратегию)
Ответ 2
- Схема наблюдателя на протяжении всего свинга (
Observable
,Observer
) - MVC также в разгаре
- Шаблон адаптера: InputStreamReader и OutputStreamWriter ПРИМЕЧАНИЕ.
ContainerAdapter
,ComponentAdapter
,FocusAdapter
,KeyAdapter
,MouseAdapter
не являются адаптерами; они на самом деле нулевые объекты. Плохой выбор имен от Sun. - Шаблон декоратора (
BufferedInputStream
может декорировать другие потоки, такие какFilterInputStream
) - Шаблон AbstractFactory для AWT Toolkit и подключаемых классов Swing.
-
java.lang.Runtime#getRuntime()
- синглтон -
ButtonGroup
для шаблона Mediator -
Action
,AbstractAction
можно использовать для разных визуальных представлений для выполнения одного и того же кода → Шаблон команды - Interned Strings или CellRender в JTable for Flyweight Pattern (также подумайте о различных пулах - Пулы потоков, пулы соединений, пулы объектов EJB - Flyweight действительно об управлении общими ресурсами)
- Модель событий Java 1.0, как и фильтры сервлетов, является примером цепочки ответственности.
- Шаблон итератора в платформе коллекций
- Вложенные контейнеры в AWT/Swing используют шаблон Composite.
- Менеджеры по раскладке в AWT/Swing являются примером стратегии
и многое другое, я думаю,
Ответ 3
- Flyweight используется с некоторыми значениями Byte, Short, Integer, Long и String.
- Фасад используется во многих местах, но наиболее очевидными являются интерфейсы Scripting.
- Singleton - java.lang.Runtime приходит на ум.
- Аннотация Factory - также скриптинг и JDBC API.
- Команда - Отменить/Вернуть TextComponent.
- Интерпретатор - RegEx (java.util.regex.) и SQL (java.sql.) API.
- Прототип - не 100% уверен, что этот счетчик, но я думаю, что метод
clone()
может быть использован для этой цели.
Ответ 4
RMI основан на прокси.
Должна быть указана одна из них для большинства 23 шаблонов в GoF:
- Аннотация Factory: интерфейсы java.sql все получают свои конкретные реализации из JDBC JAR при регистрации драйвера.
- Builder: java.lang.StringBuilder.
- Factory Метод: 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, безусловно, использует это.
- Итератор: интерфейс java.util.Iterator; не может быть яснее, чем это.
- Посредник: JMS?
- Memento:
- Наблюдатель: java.util.Observer/Observable (плохо сделано, хотя)
- Состояние:
- Стратегия:
- Шаблон:
- Посетитель:
Я не могу придумать примеры в Java для 10 из 23, но я посмотрю, смогу ли я сделать лучше завтра. Это то, что нужно для редактирования.
Ответ 5
Абстрактный шаблон Factory используется в разных местах.
Например, DatagramSocketImplFactory
, PreferencesFactory
. Есть еще много --- поиск Javadoc для интерфейсов, которые имеют имя "Factory" в их имени.
Также имеется немало примеров шаблона Factory.
Ответ 6
Несмотря на то, что я вроде как сломанные часы с этим, Java XML API использует Factory много. Я имею в виду просто посмотреть на это:
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(source);
String title = XPathFactory.newInstance().newXPath().evaluate("//title", doc);
... и т.д. и т.д.
Кроме того, различные буферы (StringBuffer, ByteBuffer, StringBuilder) используют Builder.
Ответ 7
java.util.Collection # Итератор - хороший пример метода Factory. В зависимости от конкретного подкласса Collection, который вы используете, он создаст реализацию Iterator. Поскольку и суперкласс класса Factory (коллекция), и созданный Iterator являются интерфейсами, его иногда путают с AbstractFactory. Большинство примеров для AbstractFactory в принятом ответе (BalusC) являются примерами Factory, упрощенной версии метода Factory, который не является частью оригинальных шаблонов GoF. В Facory иерархия классов Factory сбрасывается, а Factory использует другие средства для выбора возвращаемого продукта.
- Аннотация Factory
Абстрактный Factory имеет несколько методов Factory, каждый из которых создает другой продукт. Продукты, созданные одним из Factory, предназначены для совместного использования (ваш принтер и картриджи лучше от одного и того же (аннотация) factory). Как упоминалось в ответах выше, примеры компонентов графического интерфейса AWT, отличающиеся от платформы к платформе, являются примером этого (хотя его реализация отличается от структуры, описанной в Gof).