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()
(也在CharBuffer
,ShortBuffer
,IntBuffer
,IntBuffer
,FloatBuffer
和DoubleBuffer
) -
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.InputStream
,OutputStream
,Reader
和Writer
所有子类都有一个构造函数,它具有相同types的实例。 -
java.util.Collections
,checkedXXX()
,synchronizedXXX()
和unmodifiableXXX()
方法。 -
javax.servlet.http.HttpServletRequestWrapper
和HttpServletResponseWrapper
Facade (可由内部使用不同独立抽象/接口types的实例的行为方法识别)
-
javax.faces.context.FacesContext
,它内部使用了其他的抽象/接口typesLifeCycle
,ViewHandler
,NavigationHandler
等等,没有那enduser必须担心它(但是可以通过注入覆盖)。 -
javax.faces.context.ExternalContext
,它内部使用ServletContext
,HttpSession
,HttpServletRequest
,HttpServletResponse
等
享元 (可以通过创build方法返回一个caching的实例,有点“多重”的想法)
-
java.lang.Integer#valueOf(int)
(同样在Boolean
,Byte
,Character
,Short
,Long
和BigDecimal
)
代理 (可以通过创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.ExecutorService
(invokeXXX()
和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.HttpServlet
,service()
和所有的doXXX()
方法使用HttpServletRequest
和HttpServletResponse
,并且实现者必须处理它们(而不是把它们作为实例variables!)。 -
javax.servlet.Filter#doFilter()
模板方法 (可由行为方法识别,已经具有由抽象types定义的“默认”行为)
-
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()
方法都会向响应发送一个HTTP 405“Method Not Allowed”错误。 你可以自由地实现没有或任何一个。
访问者 (可以通过两种不同的抽象/接口types来识别, 这些抽象/接口types具有定义了其他抽象/接口types的方法;一个实际上调用另一个的方法,另一个执行所需的策略)
-
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
- 全程观察模式(
Observable
,Observer
) - MVC也在摆动
- 适配器模式:InputStreamReader和OutputStreamWriter注意:
ContainerAdapter
,ComponentAdapter
,FocusAdapter
,KeyAdapter
,MouseAdapter
不是适配器; 他们实际上是空的对象。 Sun的命名select太差 - 装饰模式(
BufferedInputStream
可以装饰其他stream如FilterInputStream
) - AWT工具包和Swing可插入外观类的AbstractFactory模式
-
java.lang.Runtime#getRuntime()
是单例 - 调解者模式的
ButtonGroup
-
Action
,AbstractAction
可以用于不同的视觉再现,以执行相同的代码 – >命令模式 - 用于Flyweight模式的JTable中的Interned Strings或CellRender(也可以考虑各种池 – 线程池,连接池,EJB对象池 – Flyweight实际上是关于共享资源的pipe理)
- Java 1.0事件模型就像Servletfilter一样是责任链的一个例子。
- 集合框架中的迭代器模式
- AWT / Swing中的嵌套容器使用复合模式
- AWT / Swing中的布局pipe理员是策略的一个例子
还有更多我猜
- Flyweight与Byte,Short,Integer,Long和String的一些值一起使用。
- Facade被用在许多地方,但最明显的是脚本接口。
- 单例 – java.lang.Runtime浮现在脑海。
- 抽象工厂 – 也是脚本和JDBC API。
- 命令 – TextComponent的撤销/重做。
- 解释器 – RegEx(java.util.regex。 )和SQL(java.sql。 )API。
- 原型 – 不是100%肯定,如果这个计数,但我thinkg
clone()
方法可以用于这个目的。
RMI基于代理。
应该可以引用GoF中23种模式中的大多数:
- 抽象工厂:java.sql接口在驱动程序注册时都从JDBC JAR获取具体的实现。
- Builder:java.lang.StringBuilder。
- 工厂方法:XML工厂,等等。
- 原型:也许克隆(),但我不知道我买的。
- Singleton:java.lang.System
- 适配器:java.awt.event中的适配器类,例如WindowAdapter。
- Bridge:java.util中的集合类。 由ArrayList实现的列表。
- 复合:java.awt。 java.awt.Component + java.awt.Container
- 装饰者:遍布java.io包。
- Facade: ExternalContextperformance为执行cookie,会话范围和类似操作的外观。
- Flyweight:整数,字符等
- 代理:java.rmi包
- 责任链:Servletfilter
- 命令:摆动菜单项
- 解释器:没有直接在JDK中,但JavaCC肯定使用这个。
- Iterator:java.util.Iterator接口; 不能比这更清楚。
- 调解员:JMS?
- 纪念:
- 观察者:java.util.Observer / Observable(虽然做得不好)
- 州:
- 战略:
- 模板:
- 游客:
我不能在23岁的时候用Java中的10个例子,但是我会看看明天能否做得更好。 这就是编辑的目的。
抽象工厂模式在各个地方使用。 例如, DatagramSocketImplFactory
, PreferencesFactory
。 还有更多 – 在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中描述的结构)。