我正在学习GoF Java设计模式,我想看到一些现实生活中的例子。Java核心库中有哪些设计模式的好例子?


当前回答

你可以在维基百科上找到很多设计模式的概述。它还提到了GoF提到的模式。我将在这里总结它们,并尝试分配尽可能多的模式实现,这些实现在Java SE和Java EE api中都可以找到。


创建型模式

抽象工厂(可通过创建方法识别,返回工厂本身,从而可以用于创建另一个抽象/接口类型)

javax . xml parsers DocumentBuilderFactory # newInstance()。 javax . xml 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 () charset # forName () urlstreamhandlerfactory(返回每个协议的单个对象) java.util.EnumSet # () jaxbcontext #createMarshaller()和其他类似的方法

原型(可通过创建方法识别,返回具有相同属性的不同自身实例)

object #clone()(该类必须实现java.lang.Cloneable)

单例(可通过创建方法每次返回相同的实例(通常是其本身)来识别)

朗。java Runtime # getRuntime () # getDesktop桌面java . awt。() 朗。系统/ getSecurityManager (java)


结构模式

适配器(可通过创建方法识别,该方法采用不同抽象/接口类型的实例,并返回自己/另一个抽象/接口类型的实现,该实现装饰/覆盖给定实例)

java.util.Arrays # asList () java.util.Collections #列表() java.util.Collections #枚举() java.io.InputStreamReader(返回一个Reader) java.io.OutputStreamWriter(OutputStream)(返回写入器) javax.xml.bind.annotation.adapters.XmlAdapter#marshal()和#unmarshal()

桥接(可通过创建方法识别,该方法获取不同抽象/接口类型的实例,并返回自己的抽象/接口类型的实现,该实现委托/使用给定实例)

现在还想不起来。一个虚构的例子是new LinkedHashMap(LinkedHashSet<K>, List<V>),它返回一个不可修改的链接映射,它不克隆项目,而是使用它们。然而,java.util.Collections#newSetFromMap()和singletonXXX()方法非常接近。

复合(可通过行为方法将相同抽象/接口类型的实例放入树结构中进行识别)

container #add(组件)(几乎在整个Swing中) uicomponent #getChildren()(实际上是整个JSF UI)

装饰器(可以通过采用相同抽象/接口类型实例的创建方法来识别,这增加了额外的行为)

java.io的所有子类。InputStream、OutputStream、Reader和Writer都有一个构造函数,该构造函数采用相同类型的实例。 java.util。集合,checkedXXX(), synchronizedXXX()和unmodifiableXXX()方法。 java .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)(也适用于布尔值,字节,字符,短,长和BigDecimal)

代理(可通过创建方法识别,它返回给定抽象/接口类型的实现,然后委托/使用给定抽象/接口类型的不同实现)

java.lang.reflect.Proxy java.rmi。* ejb(此处解释) inject(此处解释) javax.persistence.PersistenceContext


行为模式

责任链(可通过行为方法识别,行为方法(间接地)在队列中相同抽象/接口类型的另一个实现中调用相同的方法)

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

命令(可由抽象/接口类型中的行为方法识别,该方法调用不同抽象/接口类型的实现中的方法,该方法在创建过程中已被命令实现封装)

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的所有实现

中介(可以通过行为方法识别,它采用不同抽象/接口类型的实例(通常使用命令模式),委托/使用给定实例)

timer(所有scheduleXXX()方法) java.util.concurrent.Executor # execute () concurrent. executorservice (invokeXXX()和submit()方法) concurrent. scheduledexecutorservice(所有scheduleXXX()方法) java.lang.reflect.Method # invoke ()

纪念品(可通过行为方法识别,在内部改变整个实例的状态)

Date (setter方法可以做到这一点,Date在内部由一个长值表示) java.io.Serializable的所有实现 javax.faces.component.StateHolder的所有实现

观察者(或发布/订阅)(可由行为方法识别,它调用另一个抽象/接口类型实例上的方法,这取决于自己的状态)

java.util.Observer / java.util。可观察的(但在现实世界中很少使用) java.util.EventListener的所有实现(实际上是Swing中的所有实现) javax.servlet.http.HttpSessionBindingListener javax.servlet.http.HttpSessionAttributeListener javax.faces.event.PhaseListener

状态(可通过行为方法识别,该方法根据实例的状态改变其行为,可以在外部控制)

#execute()(由FacesServlet控制,行为取决于JSF生命周期的当前阶段(状态))

策略(可由抽象/接口类型中的行为方法识别,该方法调用不同抽象/接口类型的实现中的方法,该方法已作为方法参数传入策略实现)

java.util.Comparator#compare(),由Collections#sort()执行。 javax.servlet.http。HttpServlet, service()和所有doXXX()方法接受HttpServletRequest和HttpServletResponse,实施者必须处理它们(而不是将它们作为实例变量!) doFilter () javax.servlet.Filter #

模板方法(可以通过已经具有抽象类型定义的“默认”行为的行为方法识别)

java.io的所有非抽象方法。InputStream, io。OutputStream, java.io.Reader和java.io.Writer。 java.util的所有非抽象方法。java.util.AbstractSet和java.util.AbstractMap。 javax.servlet.http。在HttpServlet中,所有doXXX()方法默认向响应发送一个HTTP 405“Method Not Allowed”错误。您可以自由地实现其中任何一个或任何一个。

访问者(可由两种不同的抽象/接口类型识别,其中定义了各自接受另一种抽象/接口类型的方法;一个实际调用另一个的方法,另一个在它上面执行所需的策略)

annotation value和AnnotationValueVisitor lang.model.element. element和ElementVisitor java .lang.model.type. typemirror和TypeVisitor java.nio.file.FileVisitor和SimpleFileVisitor javax。faces。component。visit。visitcontext和VisitCallback

其他回答

Flyweight用于字节,短,整数,长和字符串的一些值。 Facade被用在很多地方,但最明显的是脚本接口。 单例-想到java.lang.Runtime。 抽象工厂-也脚本和JDBC API。 命令- TextComponent的撤销/重做。 解释器- RegEx (java.util.regex.)和SQL (java.sql.)API。 原型-不是100%确定这是否算数,但我认为clone()方法可以用于此目的。

RMI是基于Proxy的。

应该可以为GoF中的23种模式中的大多数引用一个:

Abstract Factory: java.sql interfaces all get their concrete implementations from JDBC JAR when driver is registered. Builder: java.lang.StringBuilder. Factory Method: XML factories, among others. Prototype: Maybe clone(), but I'm not sure I'm buying that. Singleton: java.lang.System Adapter: Adapter classes in java.awt.event, e.g., WindowAdapter. Bridge: Collection classes in java.util. List implemented by ArrayList. Composite: java.awt. java.awt.Component + java.awt.Container Decorator: All over the java.io package. Facade: ExternalContext behaves as a facade for performing cookie, session scope and similar operations. Flyweight: Integer, Character, etc. Proxy: java.rmi package Chain of Responsibility: Servlet filters Command: Swing menu items Interpreter: No directly in JDK, but JavaCC certainly uses this. Iterator: java.util.Iterator interface; can't be clearer than that. Mediator: JMS? Memento: Observer: java.util.Observer/Observable (badly done, though) State: Strategy: Template: Visitor:

在这23个例子中,我想不出10个是用Java写的,但我会看看明天是否能做得更好。这就是编辑的作用。

你可以在维基百科上找到很多设计模式的概述。它还提到了GoF提到的模式。我将在这里总结它们,并尝试分配尽可能多的模式实现,这些实现在Java SE和Java EE api中都可以找到。


创建型模式

抽象工厂(可通过创建方法识别,返回工厂本身,从而可以用于创建另一个抽象/接口类型)

javax . xml parsers DocumentBuilderFactory # newInstance()。 javax . xml 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 () charset # forName () urlstreamhandlerfactory(返回每个协议的单个对象) java.util.EnumSet # () jaxbcontext #createMarshaller()和其他类似的方法

原型(可通过创建方法识别,返回具有相同属性的不同自身实例)

object #clone()(该类必须实现java.lang.Cloneable)

单例(可通过创建方法每次返回相同的实例(通常是其本身)来识别)

朗。java Runtime # getRuntime () # getDesktop桌面java . awt。() 朗。系统/ getSecurityManager (java)


结构模式

适配器(可通过创建方法识别,该方法采用不同抽象/接口类型的实例,并返回自己/另一个抽象/接口类型的实现,该实现装饰/覆盖给定实例)

java.util.Arrays # asList () java.util.Collections #列表() java.util.Collections #枚举() java.io.InputStreamReader(返回一个Reader) java.io.OutputStreamWriter(OutputStream)(返回写入器) javax.xml.bind.annotation.adapters.XmlAdapter#marshal()和#unmarshal()

桥接(可通过创建方法识别,该方法获取不同抽象/接口类型的实例,并返回自己的抽象/接口类型的实现,该实现委托/使用给定实例)

现在还想不起来。一个虚构的例子是new LinkedHashMap(LinkedHashSet<K>, List<V>),它返回一个不可修改的链接映射,它不克隆项目,而是使用它们。然而,java.util.Collections#newSetFromMap()和singletonXXX()方法非常接近。

复合(可通过行为方法将相同抽象/接口类型的实例放入树结构中进行识别)

container #add(组件)(几乎在整个Swing中) uicomponent #getChildren()(实际上是整个JSF UI)

装饰器(可以通过采用相同抽象/接口类型实例的创建方法来识别,这增加了额外的行为)

java.io的所有子类。InputStream、OutputStream、Reader和Writer都有一个构造函数,该构造函数采用相同类型的实例。 java.util。集合,checkedXXX(), synchronizedXXX()和unmodifiableXXX()方法。 java .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)(也适用于布尔值,字节,字符,短,长和BigDecimal)

代理(可通过创建方法识别,它返回给定抽象/接口类型的实现,然后委托/使用给定抽象/接口类型的不同实现)

java.lang.reflect.Proxy java.rmi。* ejb(此处解释) inject(此处解释) javax.persistence.PersistenceContext


行为模式

责任链(可通过行为方法识别,行为方法(间接地)在队列中相同抽象/接口类型的另一个实现中调用相同的方法)

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

命令(可由抽象/接口类型中的行为方法识别,该方法调用不同抽象/接口类型的实现中的方法,该方法在创建过程中已被命令实现封装)

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的所有实现

中介(可以通过行为方法识别,它采用不同抽象/接口类型的实例(通常使用命令模式),委托/使用给定实例)

timer(所有scheduleXXX()方法) java.util.concurrent.Executor # execute () concurrent. executorservice (invokeXXX()和submit()方法) concurrent. scheduledexecutorservice(所有scheduleXXX()方法) java.lang.reflect.Method # invoke ()

纪念品(可通过行为方法识别,在内部改变整个实例的状态)

Date (setter方法可以做到这一点,Date在内部由一个长值表示) java.io.Serializable的所有实现 javax.faces.component.StateHolder的所有实现

观察者(或发布/订阅)(可由行为方法识别,它调用另一个抽象/接口类型实例上的方法,这取决于自己的状态)

java.util.Observer / java.util。可观察的(但在现实世界中很少使用) java.util.EventListener的所有实现(实际上是Swing中的所有实现) javax.servlet.http.HttpSessionBindingListener javax.servlet.http.HttpSessionAttributeListener javax.faces.event.PhaseListener

状态(可通过行为方法识别,该方法根据实例的状态改变其行为,可以在外部控制)

#execute()(由FacesServlet控制,行为取决于JSF生命周期的当前阶段(状态))

策略(可由抽象/接口类型中的行为方法识别,该方法调用不同抽象/接口类型的实现中的方法,该方法已作为方法参数传入策略实现)

java.util.Comparator#compare(),由Collections#sort()执行。 javax.servlet.http。HttpServlet, service()和所有doXXX()方法接受HttpServletRequest和HttpServletResponse,实施者必须处理它们(而不是将它们作为实例变量!) doFilter () javax.servlet.Filter #

模板方法(可以通过已经具有抽象类型定义的“默认”行为的行为方法识别)

java.io的所有非抽象方法。InputStream, io。OutputStream, java.io.Reader和java.io.Writer。 java.util的所有非抽象方法。java.util.AbstractSet和java.util.AbstractMap。 javax.servlet.http。在HttpServlet中,所有doXXX()方法默认向响应发送一个HTTP 405“Method Not Allowed”错误。您可以自由地实现其中任何一个或任何一个。

访问者(可由两种不同的抽象/接口类型识别,其中定义了各自接受另一种抽象/接口类型的方法;一个实际调用另一个的方法,另一个在它上面执行所需的策略)

annotation value和AnnotationValueVisitor lang.model.element. element和ElementVisitor java .lang.model.type. typemirror和TypeVisitor java.nio.file.FileVisitor和SimpleFileVisitor javax。faces。component。visit。visitcontext和VisitCallback

抽象工厂模式被用在很多地方。 例如,DatagramSocketImplFactory, PreferencesFactory。还有很多——在Javadoc中搜索名称中包含“Factory”的接口。

同样,工厂模式也有相当多的实例。

尽管我对这一点有点不熟悉,但Java XML API经常使用Factory。我是说看看这个:

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

...诸如此类。

此外,各种缓冲区(StringBuffer, ByteBuffer, StringBuilder)使用Builder。