estructurales - Ejemplos de patrones de diseño de GoF en las bibliotecas principales de Java
patrones de diseño java ejemplos (7)
Estoy aprendiendo GoF Java Design Patterns y quiero ver algunos ejemplos reales de ellos. ¿Cuáles son algunos buenos ejemplos de estos patrones de diseño en las bibliotecas principales de Java?
- Patrón de observador en todo el swing (
Observable
,Observer
) - MVC también en swing
- Patrón de adaptador: InputStreamReader y OutputStreamWriter NOTA:
ContainerAdapter
,ComponentAdapter
,FocusAdapter
,KeyAdapter
,MouseAdapter
no son adaptadores; En realidad son objetos nulos. Mala elección de nombres por parte de Sun. - Patrón decorador (
BufferedInputStream
puede decorar otras transmisiones comoFilterInputStream
) - Patrón AbstractFactory para el AWT Toolkit y las clases de apariencia interactiva Swing
-
java.lang.Runtime#getRuntime()
es Singleton -
ButtonGroup
deButtonGroup
para patrón de mediador -
Action
,AbstractAction
se puede usar para diferentes representaciones visuales para ejecutar el mismo código -> Patrón de comando - Cadenas internadas o CellRender en JTable para Flyweight Pattern (también piense en varias agrupaciones - agrupaciones de hebras, agrupaciones de conexiones, agrupaciones de objetos EJB - Flyweight realmente trata sobre la gestión de recursos compartidos)
- El modelo de eventos Java 1.0 es un ejemplo de Cadena de Responsabilidad, al igual que los Filtros de Servlets.
- Patrón de iterador en el marco de colecciones
- Los contenedores anidados en AWT / Swing usan el patrón Compuesto
- Los gestores de diseño en AWT / Swing son un ejemplo de estrategia
y muchos más supongo
- El peso mosca se usa con algunos valores de Byte, Short, Integer, Long y String.
- La fachada se usa en muchos lugares, pero la más obvia son las interfaces de secuencias de comandos.
- Singleton - java.lang.Runtime viene a la mente.
- Abstract Factory - También scripting y API JDBC.
- Comando - TextComponent''s Undo / Redo.
- Intérprete - RegEx (java.util.regex. ) Y SQL (java.sql. ) API.
- Prototipo : no estoy seguro al 100% de este recuento, pero creo que el método
clone()
se puede utilizar para este propósito.
A pesar de que con este tipo de reloj no funciona, Java API de Java usa mucho Factory. Me refiero a mirar 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) utilizan Builder.
El patrón de Abstract Factory se utiliza en varios lugares. Por ejemplo, DatagramSocketImplFactory
, PreferencesFactory
. Hay muchos más --- busque en el Javadoc las interfaces que tienen la palabra "Factory" en su nombre.
También hay bastantes instancias del patrón de Fábrica, también.
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í y trataré de asignar tantas implementaciones de patrones como sea posible, que se encuentran tanto en las API de Java SE como en las de Java EE.
Patrones creacionales
Fábrica abstracta (reconocible por los métodos de creación que devuelven la propia fábrica, que a su vez se puede utilizar para crear otro tipo de interfaz / resumen)
javax.xml.parsers.DocumentBuilderFactory#newInstance()
-
javax.xml.transform.TransformerFactory#newInstance()
-
javax.xml.xpath.XPathFactory#newInstance()
Builder (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 enCharBuffer
,ShortBuffer
,IntBuffer
,LongBuffer
,FloatBuffer
yDoubleBuffer
) -
javax.swing.GroupLayout.Group#addComponent()
- Todas las implementaciones de
java.lang.Appendable
-
java.util.stream.Stream.Builder
Método de fábrica (reconocible por los métodos de creación que devuelven una implementación de un tipo de interfaz / resumen)
-
java.util.Calendar#getInstance()
-
java.util.ResourceBundle#getBundle()
-
java.text.NumberFormat#getInstance()
-
java.nio.charset.Charset#forName()
-
java.net.URLStreamHandlerFactory#createURLStreamHandler(String)
(devuelve el objeto singleton por protocolo) -
java.util.EnumSet#of()
-
javax.xml.bind.JAXBContext#createMarshaller()
y otros métodos similares
Prototype (reconocible por métodos de creación que devuelven una instancia diferente de sí mismo con las mismas propiedades)
-
java.lang.Object#clone()
(la clase debe implementarjava.lang.Cloneable
)
Singleton (reconocible por métodos creacionales que devuelven la misma instancia (generalmente de sí mismo) cada vez)
Patrones estructurales
Adapter (reconocible por métodos de creación que toman una instancia de diferente tipo de interfaz / resumen y devuelven una implementación de tipo de interfaz / propio 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 unReader
) -
java.io.OutputStreamWriter(OutputStream)
(devuelve unWriter
) -
javax.xml.bind.annotation.adapters.XmlAdapter#marshal()
y#unmarshal()
Bridge (reconocible por métodos de creación que toman una instancia de diferente tipo de interfaz / resumen y devuelven una implementación de tipo de interfaz / resumen propio que delega / usa la instancia dada)
- Ninguno viene a la mente todavía. Un ejemplo ficticio sería el
new LinkedHashMap(LinkedHashSet<K>, List<V>)
que devuelve un mapa vinculado no modificable que no clona los elementos, sino que los utiliza . Sin embargo, los métodosjava.util.Collections#newSetFromMap()
ysingletonXXX()
se acercan.
Composite (reconocible por métodos de comportamiento que toman una instancia del mismo tipo de interfaz / resumen en una estructura de árbol)
-
java.awt.Container#add(Component)
(prácticamente todo el Swing por lo tanto) -
javax.faces.component.UIComponent#getChildren()
(prácticamente toda la interfaz de usuario JSF)
Decorator (reconocible por métodos de creación que toman una instancia del mismo tipo de interfaz / resumen que agrega un comportamiento adicional)
- Todas las subclases de
java.io.InputStream
,OutputStream
,Reader
yWriter
tienen un constructor que toma una instancia del mismo tipo. -
java.util.Collections
, loscheckedXXX()
,synchronizedXXX()
yunmodifiableXXX()
. -
javax.servlet.http.HttpServletRequestWrapper
yHttpServletResponseWrapper
-
javax.swing.JScrollPane
Facade (reconocible por métodos de comportamiento que utilizan internamente instancias de diferentes tipos de interfaz / resumen independientes)
-
javax.faces.context.FacesContext
, utiliza internamente, entre otros, los tipos abstractos / de interfazLifeCycle
,ViewHandler
,NavigationHandler
y muchos más sin que el usuario final tenga que preocuparse por ello (que, sin embargo, se pueden anular mediante inyección). -
javax.faces.context.ExternalContext
, que utiliza internamenteServletContext
,HttpSession
,HttpServletRequest
,HttpServletResponse
, etc.
Flyweight (reconocible por métodos de creación que devuelven una instancia en caché, un poco la idea "multiton")
-
java.lang.Integer#valueOf(int)
(también enBoolean
,Byte
,Character
,Short
,Long
yBigDecimal
)
Proxy (reconocible por métodos de creación que devuelve una implementación del 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 de interfaz / resumen en una cola)
Command (reconocible por métodos de comportamiento en un tipo de interfaz / resumen que invoca un método en una implementación de un tipo de interfaz / resumen 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
Interpreter (reconocible por métodos de comportamiento que devuelven una instancia / tipo estructuralmente diferente de la instancia / tipo dada; tenga en cuenta que el análisis / formateo no es parte del patrón, determinar el patrón y cómo aplicarlo)
-
java.util.Pattern
-
java.text.Normalizer
- Todas las subclases de
java.text.Format
- Todas las subclases de
javax.el.ELResolver
Iterator (reconocible por métodos de comportamiento que devuelven secuencialmente instancias de un tipo diferente de una cola)
- Todas las implementaciones de
java.util.Iterator
(por lo tanto, entre otras tambiénjava.util.Scanner
!). - Todas las implementaciones de
java.util.Enumeration
Mediator (reconocible por métodos de comportamiento que toman una instancia de diferente tipo de interfaz / resumen (usualmente usando el patrón de comando) que delega / usa la instancia dada)
-
java.util.Timer
(todosscheduleXXX()
métodosscheduleXXX()
) -
java.util.concurrent.Executor#execute()
-
java.util.concurrent.ExecutorService
(losinvokeXXX()
ysubmit()
) -
java.util.concurrent.ScheduledExecutorService
(todosscheduleXXX()
métodosscheduleXXX()
) -
java.lang.reflect.Method#invoke()
Memento (reconocible por métodos de comportamiento que internamente cambian el estado de toda la instancia)
-
java.util.Date
(los métodos de establecimiento hacen eso, laDate
se representa internamente por un valorlong
) - Todas las implementaciones de
java.io.Serializable
- Todas las implementaciones de
javax.faces.component.StateHolder
Observador (o publicación / suscripción) (reconocible por métodos de comportamiento que invoca un método en una instancia de otro tipo de interfaz / resumen, dependiendo del estado propio)
-
java.util.Observer
/java.util.Observable
(aunque rara vez se usa en el mundo real) - Todas las implementaciones de
java.util.EventListener
(prácticamente todo el Swing por lo tanto) -
javax.servlet.http.HttpSessionBindingListener
-
javax.servlet.http.HttpSessionAttributeListener
-
javax.faces.event.PhaseListener
State (reconocible por métodos de comportamiento que cambian su comportamiento dependiendo del estado de la instancia que se puede controlar externamente)
-
javax.faces.lifecycle.LifeCycle#execute()
(controlado porFacesServlet
, el comportamiento depende de la fase actual (estado) del ciclo de vida de JSF)
Strategy (reconocible por métodos de comportamiento en un tipo de interfaz / resumen que invoca un método en una implementación de un tipo de interfaz / resumen diferente que se ha introducido como argumento de método en la implementación de la estrategia)
-
java.util.Comparator#compare()
, ejecutado entre otrasCollections#sort()
. -
javax.servlet.http.HttpServlet
, elservice()
y todos los métodosdoXXX()
tomanHttpServletRequest
yHttpServletResponse
y el implementador debe procesarlos (¡y no obtenerlos 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
, OutputStream , Reader y Writer . - Todos los métodos no abstractos de
java.util.AbstractList
,java.util.AbstractSet
yjava.util.AbstractMap
. -
javax.servlet.http.HttpServlet
, todos los métodosdoXXX()
de forma predeterminada envían un error HTTP 405 "Método no permitido" a la respuesta. Eres libre de implementar ninguno o cualquiera de ellos.
Visitor (reconocible por dos tipos diferentes de interfaz / resumen que tiene métodos definidos que toman cada uno el otro tipo de interfaz / interfaz; el primero llama al método del otro y el otro ejecuta la estrategia deseada en él)
RMI se basa en Proxy.
Debería ser posible citar uno para la mayoría de los 23 patrones en GoF:
- Fábrica abstracta: todas las interfaces java.sql obtienen sus implementaciones concretas de JDBC JAR cuando se registra el controlador.
- Constructor: java.lang.StringBuilder.
- Método de fábrica: fábricas de XML, entre otras.
- Prototipo: tal vez clone (), pero no estoy seguro de que esté comprando eso.
- Singleton: java.lang.System
- Adaptador: Clases de adaptador en java.awt.event, por ejemplo, WindowAdapter.
- Puente: Clases de colección en java.util. Lista implementada por ArrayList.
- Compuesto: java.awt. java.awt.Component + java.awt.Container
- Decorador: Todo sobre el paquete java.io.
- Fachada: ExternalContext comporta como una fachada para realizar cookies, alcance de sesión y operaciones similares.
- Peso de mosca: Entero, personaje, etc.
- Proxy: paquete java.rmi
- Cadena de Responsabilidad: Filtros de Servlets.
- Comando: Swing elementos de menú
- Intérprete: no directamente en JDK, pero JavaCC ciertamente usa esto.
- Iterator: java.util.Iterator interface; no puede ser más claro que eso
- Mediador: JMS?
- Recuerdo:
- Observer: java.util.Observer/Observable (aunque mal hecho)
- Estado:
- Estrategia:
- Modelo:
- Visitante:
No puedo pensar en ejemplos en Java para 10 de los 23, pero veré si puedo hacerlo mejor mañana. Para eso está la edición.
java.util.Collection # Iterator es un buen ejemplo de un método de fábrica. Dependiendo de la subclase concreta de la Colección que utilice, creará una implementación de Iterador. Debido a que tanto la superclase de Fábrica (Colección) como el Iterador 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 de Fábrica está colapsada y la fábrica utiliza otros medios para elegir el producto a 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 diseñados para usarse juntos (es mejor que su impresora y cartuchos sean de la misma fábrica (resumen)). Como se mencionó en las respuestas anteriores, las familias de componentes 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).