Примеры шаблонов проектирования 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.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
  1. Схема наблюдателя на протяжении всего свинга (Observable, Observer)
  2. MVC также в разгаре
  3. Шаблон адаптера: InputStreamReader и OutputStreamWriter ПРИМЕЧАНИЕ. ContainerAdapter, ComponentAdapter, FocusAdapter, KeyAdapter, MouseAdapter не являются адаптерами; они на самом деле нулевые объекты. Плохой выбор имен от Sun.
  4. Шаблон декоратора (BufferedInputStream может украсить другие потоки, такие как FilterInputStream)
  5. Шаблон AbstractFactory для AWT Toolkit и подключаемых классов Swing.
  6. java.lang.Runtime#getRuntime() Синглтон
  7. ButtonGroup для шаблона Mediator
  8. Action, AbstractAction может использоваться для разных визуальных представлений для выполнения одного и того же кода -> Шаблон команды
  9. Interned Strings или CellRender в JTable for Flyweight Pattern (также подумайте о различных пулах - Пулы потоков, пулы соединений, пулы объектов EJB - Flyweight действительно об управлении общими ресурсами)
  10. Модель событий Java 1.0, как и фильтры сервлетов, является примером цепочки ответственности.
  11. Шаблон итератора в платформе коллекций
  12. Вложенные контейнеры в AWT/Swing используют шаблон Composite.
  13. Менеджеры по раскладке в AWT/Swing являются примером стратегии

и многое другое, я думаю,

  1. Flyweight используется с некоторыми значениями Byte, Short, Integer, Long и String.
  2. Фасад используется во многих местах, но наиболее очевидным является интерфейс сценариев.
  3. Синглтон - java.lang. Время приходит на ум.
  4. Абстрактная Фабрика - также Сценарии и JDBC API.
  5. Команда - Отменить / Повторить TextComponent.
  6. Интерпретатор - RegEx (java.util.regex.) И SQL (java.sql.) API.
  7. Прототип - Не уверен на 100%, если это рассчитывать, но я думаю, clone() метод может быть использован для этой цели.

RMI основан на Прокси.

Должна быть возможность процитировать один из 23 шаблонов в GoF:

  1. Абстрактная фабрика: все интерфейсы java.sql получают свои конкретные реализации из JDBC JAR при регистрации драйвера.
  2. Строитель: java.lang.StringBuilder.
  3. Фабрика Метод: фабрики XML, среди других.
  4. Прототип: Может быть, clone(), но я не уверен, что покупаю это.
  5. Синглтон: java.lang.System
  6. Адаптер: классы адаптера в java.awt.event, например, WindowAdapter.
  7. Мост: Коллекция классов в java.util. Список реализован ArrayList.
  8. Композитный: java.awt. java.awt.Component + java.awt.Container
  9. Декоратор: по всему пакету java.io.
  10. Фасад: ExternalContext ведет себя как фасад для выполнения файлов cookie, области сеанса и аналогичных операций.
  11. Flyweight: целое число, символ и т. Д.
  12. Прокси: пакет java.rmi
  13. Цепочка ответственности: фильтры сервлетов
  14. Команда: Swing пункты меню
  15. Интерпретатор: Нет напрямую в JDK, но JavaCC, безусловно, использует это.
  16. Iterator: интерфейс java.util.Iterator; не может быть яснее, чем это.
  17. Посредник: JMS?
  18. Memento:
  19. Наблюдатель: java.util.Observer/Observable (правда, плохо)
  20. Государственный:
  21. Стратегия:
  22. Шаблон:
  23. Посетитель:

Я не могу думать о примерах в 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.

Другие вопросы по тегам