Ejemplos de patrones de diseño GoF en las bibliotecas centrales de Java

Estoy aprendiendo GoF Java Design Patterns y quiero ver algunos ejemplos de vida real de ellos. ¿Cuáles son algunos buenos ejemplos de estos patrones de diseño en las bibliotecas centrales de Java?

Puede encontrar una descripción general de muchos patrones de diseño en Wikipedia . También menciona qué patrones son mencionados por GoF. Los resumiré aquí e intentaré asignar tantas implementaciones de patrones como sea posible, que se encuentran en las API de Java EE y Java EE.


Patrones creacionales

Fábrica abstracta (reconocible por métodos creacionales que devuelven la propia fábrica que a su vez puede usarse para crear otro tipo de resumen / interfaz)

  • javax.xml.parsers.DocumentBuilderFactory#newInstance()
  • javax.xml.transform.TransformerFactory#newInstance()
  • javax.xml.xpath.XPathFactory#newInstance()

Constructor (reconocible por métodos creacionales que devuelven la instancia en sí)

  • java.lang.StringBuilder#append() (no sincronizado)
  • java.lang.StringBuffer#append() (sincronizado)
  • java.nio.ByteBuffer#put() (también en CharBuffer , ShortBuffer , IntBuffer , LongBuffer , FloatBuffer y DoubleBuffer )
  • javax.swing.GroupLayout.Group#addComponent()
  • Todas las implementaciones de java.lang.Appendable
  • java.util.stream.Stream.Builder

Método de fábrica (que se puede reconocer mediante métodos creacionales que devuelven una implementación de un tipo abstracto / de interfaz)

  • java.util.Calendar#getInstance()
  • java.util.ResourceBundle#getBundle()
  • java.text.NumberFormat#getInstance()
  • java.nio.charset.Charset#forName()
  • java.net.URLStreamHandlerFactory#createURLStreamHandler(String) (Devuelve un objeto singleton por protocolo)
  • java.util.EnumSet#of()
  • javax.xml.bind.JAXBContext#createMarshaller() y otros métodos similares

Prototipo (reconocible por métodos creacionales que devuelven una instancia diferente de sí mismo con las mismas propiedades)

  • java.lang.Object#clone() (la clase tiene que implementar java.lang.Cloneable )

Singleton (reconocible por métodos creacionales que devuelven la misma instancia (generalmente de sí mismo) cada vez)

  • java.lang.Runtime#getRuntime()
  • java.awt.Desktop#getDesktop()
  • java.lang.System#getSecurityManager()

Patrones estructurales

Adaptador (que se puede reconocer mediante métodos creacionales que toman una instancia de diferente tipo de resumen / interfaz y devuelve una implementación de tipo de interfaz / abstracto propio / otro que decora / anula la instancia dada)

  • java.util.Arrays#asList()
  • java.util.Collections#list()
  • java.util.Collections#enumeration()
  • java.io.InputStreamReader(InputStream) (devuelve un Reader )
  • java.io.OutputStreamWriter(OutputStream) (devuelve un Writer )
  • javax.xml.bind.annotation.adapters.XmlAdapter#marshal() y #unmarshal()

Bridge (que se puede reconocer mediante métodos creativos que toman una instancia de diferente tipo de resumen / interfaz y que devuelve una implementación del tipo abstracto / interfaz propio que delega / usa la instancia dada)

  • Ninguno viene a la mente todavía. Un ejemplo ficticio sería el new LinkedHashMap(LinkedHashSet, List) que devuelve un mapa vinculado no modificable que no clona los artículos, sino que los usa . Sin embargo, los métodos java.util.Collections#newSetFromMap() y singletonXXX() se acercan.

Compuesto (reconocible por métodos de comportamiento que toman una instancia del mismo tipo abstracto / interfaz en una estructura de árbol)

  • java.awt.Container#add(Component) (prácticamente en todo Swing)
  • javax.faces.component.UIComponent#getChildren() (prácticamente todo en JSF UI por lo tanto)

Decorador (se puede reconocer mediante métodos creacionales que toman una instancia del mismo tipo abstracto / interfaz que agrega un comportamiento adicional)

  • Todas las subclases de java.io.InputStream , OutputStream , Reader y Writer tienen un constructor tomando una instancia del mismo tipo.
  • java.util.Collections , los checkedXXX() , synchronizedXXX() y unmodifiableXXX() .
  • javax.servlet.http.HttpServletRequestWrapper y HttpServletResponseWrapper
  • javax.swing.JScrollPane

Fachada (reconocible por métodos de comportamiento que usa internamente instancias de diferentes tipos abstractos / de interfaz independientes)

  • javax.faces.context.FacesContext , utiliza internamente, entre otros, los tipos abstract / interface LifeCycle , ViewHandler , NavigationHandler y muchos más sin que el usuario final tenga que preocuparse por ello (que, sin embargo, son anulables mediante inyección).
  • javax.faces.context.ExternalContext , que internamente usa ServletContext , HttpSession , HttpServletRequest , HttpServletResponse , etc.

Flyweight (reconocible por métodos creacionales que devuelven una instancia en caché, un poco la idea de “multiton”)

  • java.lang.Integer#valueOf(int) (también en Boolean , Byte , Character , Short , Long y BigDecimal )

Proxy (que se puede reconocer mediante métodos creacionales que devuelve una implementación de un tipo de interfaz / resumen dado que a su vez delega / usa una implementación diferente del tipo de interfaz / resumen dado)

  • java.lang.reflect.Proxy
  • java.rmi.*
  • javax.ejb.EJB ( explicación aquí )
  • javax.inject.Inject ( explicación aquí )
  • javax.persistence.PersistenceContext

Patrones de comportamiento

Cadena de responsabilidad (reconocible por métodos de comportamiento que (indirectamente) invoca el mismo método en otra implementación del mismo tipo abstracto / interfaz en una cola)

  • java.util.logging.Logger#log()
  • javax.servlet.Filter#doFilter()

Comando (reconocible por métodos de comportamiento en un tipo abstracto / de interfaz que invoca un método en una implementación de un tipo abstracto / interfaz diferente que ha sido encapsulado por la implementación del comando durante su creación)

  • Todas las implementaciones de java.lang.Runnable
  • Todas las implementaciones de javax.swing.Action

Intérprete (reconocible por métodos de comportamiento que devuelven una instancia / tipo estructuralmente diferente de la instancia / tipo dado; tenga en cuenta que el análisis / formateo no es parte del patrón, la determinación del patrón y la forma de aplicarlo)

  • java.util.Pattern
  • java.text.Normalizer
  • Todas las subclases de java.text.Format
  • Todas las subclases de javax.el.ELResolver

Iterador (reconocible por métodos de comportamiento que devuelve secuencialmente instancias de un tipo diferente de una cola)

  • Todas las implementaciones de java.util.Iterator (¡entre otros también java.util.Scanner !).
  • Todas las implementaciones de java.util.Enumeration

Mediador (que se puede reconocer mediante métodos de comportamiento tomando una instancia de diferente tipo de resumen / interfaz (usualmente usando el patrón de comando) que delega / usa la instancia dada)

  • java.util.Timer (todos scheduleXXX() métodos scheduleXXX() )
  • java.util.concurrent.Executor#execute()
  • java.util.concurrent.ExecutorService (los invokeXXX() y submit() )
  • java.util.concurrent.ScheduledExecutorService (todos scheduleXXX() métodos scheduleXXX() )
  • java.lang.reflect.Method#invoke()

Memento (reconocible por métodos de comportamiento que cambia internamente el estado de toda la instancia)

  • java.util.Date (los métodos setter hacen eso, la Date se representa internamente por un valor long )
  • Todas las implementaciones de java.io.Serializable
  • Todas las implementaciones de javax.faces.component.StateHolder

Observer (o Publish / Subscribe) (reconocible por métodos de comportamiento que invoca un método en una instancia de otro tipo abstracto / interfaz, dependiendo del propio estado)

  • java.util.Observer / java.util.Observable (rara vez se usa en el mundo real)
  • Todas las implementaciones de java.util.EventListener (prácticamente en todo Swing)
  • javax.servlet.http.HttpSessionBindingListener
  • javax.servlet.http.HttpSessionAttributeListener
  • javax.faces.event.PhaseListener

Estado (reconocible por métodos de comportamiento que cambia su comportamiento dependiendo del estado de la instancia que puede controlarse externamente)

  • javax.faces.lifecycle.LifeCycle#execute() (controlado por FacesServlet , el comportamiento depende de la fase actual (estado) del ciclo de vida JSF)

Estrategia (reconocible por métodos de comportamiento en un tipo abstracto / interfaz que invoca un método en una implementación de un tipo abstracto / interfaz diferente que se ha pasado como un argumento de método en la implementación de la estrategia)

  • java.util.Comparator#compare() , ejecutado entre otros Collections#sort() .
  • javax.servlet.http.HttpServlet , los métodos service() y doXXX() toman HttpServletRequest y HttpServletResponse y el implementador tiene que procesarlos (¡y no tenerlos como variables de instancia!).
  • javax.servlet.Filter#doFilter()

Método de plantilla (reconocible por métodos de comportamiento que ya tienen un comportamiento “predeterminado” definido por un tipo abstracto)

  • Todos los métodos no abstractos de java.io.InputStream , java.io.OutputStream , java.io.Reader y java.io.Writer .
  • Todos los métodos no abstractos de java.util.AbstractList , java.util.AbstractSet y java.util.AbstractMap .
  • javax.servlet.http.HttpServlet , todos los métodos doXXX() de forma predeterminada envían un error HTTP 405 “Método no permitido” a la respuesta. Eres libre de implementar ninguna o ninguna de ellas.

Visitante (reconocible por dos tipos abstractos / de interfaz diferentes que tienen métodos definidos que toman cada uno el otro tipo abstracto / interfaz, el uno realmente llama al método del otro y el otro ejecuta la estrategia deseada en él)

  • javax.lang.model.element.AnnotationValue y AnnotationValueVisitor
  • javax.lang.model.element.Element y ElementVisitor
  • javax.lang.model.type.TypeMirror y TypeVisitor
  • java.nio.file.FileVisitor y SimpleFileVisitor
  • javax.faces.component.visit.VisitContext y VisitCallback
  1. Patrón de observador durante todo el swing ( Observable , Observer )
  2. MVC también en swing
  3. Patrón de adaptador: InputStreamReader y OutputStreamWriter NOTA: ContainerAdapter , ComponentAdapter , FocusAdapter , KeyAdapter , MouseAdapter no son adaptadores; en realidad son objetos nulos. Pobre elección de nombres por Sun.
  4. Patrón decorador ( BufferedInputStream puede decorar otras transmisiones como FilterInputStream )
  5. AbstractFactory Pattern para AWT Toolkit y las clases de apariencia y efecto Swing Swing
  6. java.lang.Runtime#getRuntime() es Singleton
  7. ButtonGroup for Mediator pattern
  8. Action , AbstractAction se puede usar para diferentes representaciones visuales para ejecutar el mismo código -> Patrón de comando
  9. Interned Strings o CellRender en JTable for Flyweight Pattern (También piense en varias agrupaciones: grupos de subprocesos, grupos de conexiones, grupos de objetos EJB, Flyweight realmente trata sobre la administración de recursos compartidos)
  10. El modelo de evento de Java 1.0 es un ejemplo de Cadena de responsabilidad, al igual que los Servlets Filters.
  11. Patrón iterador en el marco de colecciones
  12. Los contenedores nesteds en AWT / Swing usan el patrón Compuesto
  13. Los administradores de diseño en AWT / Swing son un ejemplo de estrategia

y muchos más, supongo

  1. Flyweight se usa con algunos valores de Byte, Short, Integer, Long y String.
  2. Facade se utiliza en muchos lugares, pero el más obvio es las interfaces de scripting.
  3. Singleton – java.lang.Runtime viene a la mente.
  4. Abstract Factory – También secuencias de comandos y API de JDBC.
  5. Comando – Deshacer / Rehacer de TextComponent.
  6. Intérprete : API de RegEx (java.util.regex. ) Y SQL (java.sql ).
  7. Prototipo : no estoy 100% seguro de que este conteo, pero el método thinkg clone() se puede usar para este propósito.

RMI se basa en Proxy.

Debería ser posible citar uno para la mayoría de los 23 patrones en GoF:

  1. Abstract Factory: las interfaces java.sql obtienen todas sus implementaciones concretas de JDBC JAR cuando el controlador está registrado.
  2. Constructor: java.lang.StringBuilder.
  3. Método de fábrica: fábricas XML, entre otros.
  4. Prototipo: tal vez clonar (), pero no estoy seguro de que compre eso.
  5. Singleton: java.lang.System
  6. Adaptador: clases de adaptador en java.awt.event, p. Ej., WindowAdapter.
  7. Bridge: clases de colección en java.util. Lista implementada por ArrayList.
  8. Compuesto: java.awt. java.awt.Component + java.awt.Container
  9. Decorador: en todo el paquete java.io
  10. Fachada: ExternalContext se comporta como una fachada para realizar cookies, scope de sesiones y operaciones similares.
  11. Flyweight: entero, personaje, etc.
  12. Proxy: paquete java.rmi
  13. Cadena de responsabilidad: filtros de servlets
  14. Comando: elementos del menú Swing
  15. Intérprete: No directamente en JDK, pero JavaCC ciertamente usa esto.
  16. Iterador: interfaz java.util.Iterator; no puede ser más claro que eso.
  17. Mediador: JMS?
  18. Recuerdo:
  19. Observer: java.util.Observer/Observable (mal hecho, sin embargo)
  20. Estado:
  21. Estrategia:
  22. Modelo:
  23. Visitante:

No puedo pensar en ejemplos en Java para 10 de los 23, pero veré si puedo hacerlo mejor mañana. Para eso es la edición.

El patrón Abstract Factory se usa en varios lugares. Por ejemplo, DatagramSocketImplFactory , PreferencesFactory . Hay muchos más: busque el Javadoc para las interfaces que tienen la palabra “Factory” en su nombre.

También hay bastantes instancias del patrón Factory, también.

Aunque soy una especie de reloj roto con este, Java XML API usa mucho Factory. Quiero decir solo mira esto:

 Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(source); String title = XPathFactory.newInstance().newXPath().evaluate("//title", doc); 

…y así sucesivamente y así sucesivamente.

Además, varios Buffers (StringBuffer, ByteBuffer, StringBuilder) usan Builder.

  • Método de fábrica

java.util.Collection # Iterator es un buen ejemplo de un método de fábrica. Dependiendo de la subclase concreta de Colección que use, creará una implementación de iterador. Debido a que tanto la superclase Factory (Collection) como el Iterator creado son interfaces, a veces se confunde con AbstractFactory. La mayoría de los ejemplos de AbstractFactory en la respuesta aceptada (BalusC) son ejemplos de Factory , una versión simplificada de Factory Method, que no forma parte de los patrones originales de GoF. En Facory, la jerarquía de clase Factory está contraída y la fábrica utiliza otros medios para elegir el producto que se devolverá.

  • Fábrica abstracta

Una fábrica abstracta tiene múltiples métodos de fábrica, cada uno creando un producto diferente. Los productos producidos por una fábrica están destinados a ser utilizados en conjunto (la impresora y los cartuchos deben ser mejores de la misma fábrica (abstracta)). Como se menciona en las respuestas anteriores, las familias de los componentes de AWT GUI, que difieren de una plataforma a otra, son un ejemplo de esto (aunque su implementación difiere de la estructura descrita en Gof).