Java核心库中的GoFdevise模式示例

我正在学习GoF的Javadevise模式,我想看看他们的一些真实的例子。 Java核心库中这些devise模式的一些很好的例子是什么?

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


创造性的模式

抽象工厂 (可以通过创build方法来识别,返回工厂本身又可以用来创build另一个抽象/接口types)

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

生成器 (可以通过创build方法返回实例本身)

  • java.lang.StringBuilder#append() (unsynchronized)
  • java.lang.StringBuffer#append() (synchronized)
  • java.nio.ByteBuffer#put() (也在CharBufferShortBufferIntBufferIntBufferFloatBufferDoubleBuffer
  • javax.swing.GroupLayout.Group#addComponent()
  • java.lang.Appendable所有实现

工厂方法 (可由创build方法识别,返回抽象/接口types的实现)

  • 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()和其他类似的方法

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

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

单身 (可以通过创build方法每次都返回相同的实例(通常是自己)

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

结构模式

适配器 (可以通过创build方法来识别不同的抽象/接口types的实例,并返回一个实现自己/另一个抽象/接口types的装饰/覆盖给定的实例)

  • 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()

(可以通过创build方法来识别不同的抽象/接口types的实例,并返回代表/使用给定实例的自己的抽象/接口types的实现)

  • 没有人想到。 一个虚构的例子是new LinkedHashMap(LinkedHashSet<K>, List<V>) ,它返回一个不可修改的链接地图,它不克隆项目,但使用它们。 然而, java.util.Collections#newSetFromMap()singletonXXX()方法是相近的。

复合 (可以通过将相同抽象/接口types的实例转换为树结构的行为方法来识别)

  • java.awt.Container#add(Component) (几乎所有的Swing都是这样)
  • javax.faces.component.UIComponent#getChildren() (几乎遍布JSF UI)

装饰者 (可以通过创造性的方法来识别相同的抽象/接口types的实例,增加额外的行为)

  • java.io.InputStreamOutputStreamReaderWriter所有子类都有一个构造函数,它具有相同types的实例。
  • java.util.CollectionscheckedXXX()synchronizedXXX()unmodifiableXXX()方法。
  • javax.servlet.http.HttpServletRequestWrapperHttpServletResponseWrapper

Facade (可由内部使用不同独立抽象/接口types的实例的行为方法识别)

  • javax.faces.context.FacesContext ,它内部使用了其他的抽象/接口typesLifeCycleViewHandlerNavigationHandler等等,没有那enduser必须担心它(但是可以通过注入覆盖)。
  • javax.faces.context.ExternalContext ,它内部使用ServletContextHttpSessionHttpServletRequestHttpServletResponse

享元 (可以通过创build方法返回一个caching的实例,有点“多重”的想法)

  • java.lang.Integer#valueOf(int) (同样在BooleanByteCharacterShortLongBigDecimal

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

  • java.lang.reflect.Proxy
  • java.rmi.*
  • javax.ejb.EJB ( 这里解释 )
  • javax.inject.Inject ( 在这里解释 )
  • javax.persistence.PersistenceContext

行为模式

(可以通过行为方法识别(间接地)调用队列中相同抽象/接口types的另一个实现中的相同方法)

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

命令 (可以通过抽象/接口types中的行为方法来识别,该types在创build期间由命令实现封装不同抽象/接口types的实现中调用方法)

  • java.lang.Runnable所有实现
  • javax.swing.Action所有实现

解释器 (可以通过行为方法识别返回给定实例/types的结构不同的实例/types;注意parsing/格式不是模式的一部分,确定模式以及如何应用)

  • java.util.Pattern
  • java.text.Normalizer
  • java.text.Format所有子类
  • javax.el.ELResolver所有子类

迭代器 (可以通过行为方法从队列中顺序返回不同types的实例)

  • java.util.Iterator所有实现(因此也包括java.util.Scanner !)。
  • java.util.Enumeration所有实现

中介者 (可以通过行为方法来承认代理/使用给定实例的不同抽象/接口types的实例(通常使用命令模式)

  • java.util.Timer (所有的scheduleXXX()方法)
  • java.util.concurrent.Executor#execute()
  • java.util.concurrent.ExecutorServiceinvokeXXX()submit()方法)
  • java.util.concurrent.ScheduledExecutorService (所有scheduleXXX()方法)
  • java.lang.reflect.Method#invoke()

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

  • java.util.Date (setter方法是这样做的, Date是由long值内部表示的)
  • java.io.Serializable所有实现
  • javax.faces.component.StateHolder所有实现

观察者(或发布/订阅) (可由行为方法识别,根据自己的状态在另一个抽象/接口types的实例上调用方法)

  • java.util.Observer / java.util.Observable (尽pipe在现实世界java.util.Observable很less使用)
  • java.util.EventListener所有实现(几乎遍及Swing)
  • javax.servlet.http.HttpSessionBindingListener
  • javax.servlet.http.HttpSessionAttributeListener
  • javax.faces.event.PhaseListener

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

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

策略 (行为方法可以在抽象/接口types中识别,在实现不同的抽象/接口types的方法中,抽象/接口types已经作为策略实现的方法参数传入)

  • java.util.Comparator#compare() ,由其他Collections#sort()
  • javax.servlet.http.HttpServletservice()和所有的doXXX()方法使用HttpServletRequestHttpServletResponse ,并且实现者必须处理它们(而不是把它们作为实例variables!)。
  • javax.servlet.Filter#doFilter()

模板方法 (可由行为方法识别,已经具有由抽象types定义的“默认”行为)

  • java.io.InputStreamjava.io.OutputStreamjava.io.Readerjava.io.Writer所有非抽象方法。
  • java.util.AbstractListjava.util.AbstractSetjava.util.AbstractMap所有非抽象方法。
  • javax.servlet.http.HttpServlet ,默认情况下所有的doXXX()方法都会向响应发送一个HTTP 405“Method Not Allowed”错误。 你可以自由地实现没有或任何一个。

访问者 (可以通过两种不同的抽象/接口types来识别, 这些抽象/接口types具有定义了其他抽象/接口types的方法;一个实际上调用另一个的方法,另一个执行所需的策略)

  • javax.lang.model.element.AnnotationValueAnnotationValueVisitor
  • javax.lang.model.element.ElementElementVisitor
  • javax.lang.model.type.TypeMirrorTypeVisitor
  • java.nio.file.FileVisitorSimpleFileVisitor
  • javax.faces.component.visit.VisitContextVisitCallback
  1. 全程观察模式( ObservableObserver
  2. MVC也在摆动
  3. 适配器模式:InputStreamReader和OutputStreamWriter注意: ContainerAdapterComponentAdapterFocusAdapterKeyAdapterMouseAdapter 不是适配器; 他们实际上是空的对象。 Sun的命名select太差
  4. 装饰模式( BufferedInputStream可以装饰其他stream如FilterInputStream
  5. AWT工具包和Swing可插入外观类的AbstractFactory模式
  6. java.lang.Runtime#getRuntime()是单例
  7. 调解者模式的ButtonGroup
  8. ActionAbstractAction可以用于不同的视觉再现,以执行相同的代码 – >命令模式
  9. 用于Flyweight模式的JTable中的Interned Strings或CellRender(也可以考虑各种池 – 线程池,连接池,EJB对象池 – Flyweight实际上是关于共享资源的pipe理)
  10. Java 1.0事件模型就像Servletfilter一样是责任链的一个例子。
  11. 集合框架中的迭代器模式
  12. AWT / Swing中的嵌套容器使用复合模式
  13. AWT / Swing中的布局pipe理员是策略的一个例子

还有更多我猜

  1. Flyweight与Byte,Short,Integer,Long和String的一些值一起使用。
  2. Facade被用在许多地方,但最明显的是脚本接口。
  3. 单例 – java.lang.Runtime浮现在脑海。
  4. 抽象工厂 – 也是脚本和JDBC API。
  5. 命令 – TextComponent的撤销/重做。
  6. 解释器 – RegEx(java.util.regex。 )和SQL(java.sql。 )API。
  7. 原型 – 不是100%肯定,如果这个计数,但我thinkg clone()方法可以用于这个目的。

RMI基于代理。

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

  1. 抽象工厂:java.sql接口在驱动程序注册时都从JDBC JAR获取具体的实现。
  2. Builder:java.lang.StringBuilder。
  3. 工厂方法:XML工厂,等等。
  4. 原型:也许克隆(),但我不知道我买的。
  5. Singleton:java.lang.System
  6. 适配器:java.awt.event中的适配器类,例如WindowAdapter。
  7. Bridge:java.util中的集合类。 由ArrayList实现的列表。
  8. 复合:java.awt。 java.awt.Component + java.awt.Container
  9. 装饰者:遍布java.io包。
  10. Facade: ExternalContextperformance为执行cookie,会话范围和类似操作的外观。
  11. Flyweight:整数,字符等
  12. 代理:java.rmi包
  13. 责任链:Servletfilter
  14. 命令:摆动菜单项
  15. 解释器:没有直接在JDK中,但JavaCC肯定使用这个。
  16. Iterator:java.util.Iterator接口; 不能比这更清楚。
  17. 调解员:JMS?
  18. 纪念:
  19. 观察者:java.util.Observer / Observable(虽然做得不好)
  20. 州:
  21. 战略:
  22. 模板:
  23. 游客:

我不能在23岁的时候用Java中的10个例子,但是我会看看明天能否做得更好。 这就是编辑的目的。

抽象工厂模式在各个地方使用。 例如, DatagramSocketImplFactoryPreferencesFactory 。 还有更多 – 在Javadoc中search其名称中包含“Factory”字样的接口。

工厂模式也有不less例子。

即使我是这个破的时钟,Java XML API使用工厂很多。 我的意思是只看这个:

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

…等等等等。

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

  • 工厂方法

java.util.Collection#Iterator是Factory Method的一个很好的例子。 根据您使用的Collection的具体子类,它将创build一个Iterator实现。 由于Factory超类(集合)和所创build的迭代器都是接口,所以有时会与AbstractFactory混淆。 在接受的答案(BalusC)中,AbstractFactory的大多数例子都是Factory的例子, Factory是Factory Method的一个简化版本,它不是原始的GoF模式的一部分。 在Facory中,Factory类层次结构已折叠,工厂使用其他方法来select要返回的产品。

  • 抽象工厂

一个抽象工厂有多个工厂方法,每个方法创build一个不同的产品。 由一家工厂生产的产品旨在一起使用(您的打印机和墨盒最好来自同一个(抽象)工厂)。 正如在上面的答案中所提到的,AWT GUI组件的不同之处在于这个例子(尽pipe它的实现不同于Gof中描述的结构)。