Java核心库中的GoF设计模式示例


672

我正在学习GoF Java设计模式,我想看看其中的一些实际示例。Java核心库中的这些设计模式有哪些好的示例?

Answers:


3229

您可以在Wikipedia中找到许多设计模式的概述。它还提到了GoF提到了哪些模式。我将在这里对其进行总结,并尝试分配尽可能多的模式实现,这些模式实现可以在Java SE和Java EE API中找到。


创作模式

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

生成器 (可通过创建方法返回实例本身来识别)

工厂方法 (可通过返回抽象/接口类型的实现的创建方法识别)

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

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


结构模式

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

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

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

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

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

外观 (可通过内部使用不同独立抽象/接口类型的实例的行为方法识别)

Flyweight (可通过返回缓存实例的创建方法来识别,有点“多态”概念)

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


行为模式

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

命令 (通过其中调用在的实施方案的方法的抽象/接口类型行为方法recognizeable 不同已抽象/接口类型包封它的创建过程中由命令实现)

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

迭代器 (行为方法可识别,该行为方法可从队列中顺序返回不同类型的实例)

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

记忆 (可通过内部改变整个实例状态的行为方法识别)

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

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

策略 (通过在抽象/接口类型行为方法recognizeable它调用一个方法中的实施方案不同,其已被抽象/接口类型传入的作为方法参数到策略执行)

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

访客 (可通过两种不同的抽象/接口类型识别,其定义的方法彼此采用另一种抽象/接口类型;一个方法实际上调用了另一个方法/接口,而另一个方法则在其上执行了所需的策略)


23
令人印象深刻.. :) +1。javax.lang.model.element定义的游客;)我不是很确定是否doXXXdoFilter在“策略”。
博若

16
提到的构建器(例如StrinbgBuilder)都不是构建器模式的示例。但是,将他们视为构建者是一个非常常见的错误(因此,您并没有真正责怪^ _ ^)
Angel O'Sphere 2011年

77
@BalusC,我有一个问题要问你。您阅读过Java和JSF 的WHOLE源代码吗?
Tapas Bose

20
@塔帕斯:我没有阅读所有内容,只阅读了我需要的部分,或者只是对“他们”是如何做到的很好奇。
BalusC

7
“工厂方法”下的大多数示例都是不是GoF模式的“静态工厂”的示例。不正确。
环形承载者

107
  1. 整个摆动过程中的观察者模式(ObservableObserver
  2. MVC也如火如荼
  3. 适配器模式:InputStreamReader和OutputStreamWriter注:ContainerAdapterComponentAdapterFocusAdapterKeyAdapterMouseAdapter适配器; 它们实际上是空对象。Sun命名选择不佳。
  4. 装饰器模式(BufferedInputStream可以装饰其他流,例如FilterInputStream
  5. AWT工具包和Swing可插入外观类的AbstractFactory模式
  6. java.lang.Runtime#getRuntime() 是辛格尔顿
  7. ButtonGroup 用于调解员模式
  8. ActionAbstractAction可用于不同的视觉表示以执行相同的代码->命令模式
  9. 用于Flyweight模式的JTable中的内部字符串或CellRender(也请考虑各种池-线程池,连接池,EJB对象池-Flyweight实际上是关于共享资源的管理)
  10. Java 1.0事件模型是“责任链”的一个示例,Servlet过滤器也是如此。
  11. Collections Framework中的迭代器模式
  12. AWT / Swing中的嵌套容器使用Composite模式
  13. AWT / Swing中的布局管理器是策略的一个示例

我猜还有更多


1
感谢有关MouseAdapter的提示。我发现了这个问题:stackoverflow.com/questions/9244185/…–
林肯

请注意,Swing 仅宽松地基于 MVC。它已将View和Controller折叠为一个类。
马提亚斯·布劳恩

51
  1. Flyweight与Byte,Short,Integer,Long和String的某些值一起使用。
  2. 门面在很多地方都使用过,但是最明显的是脚本接口。
  3. Singleton-我想到了java.lang.Runtime。
  4. 抽象工厂 -脚本和JDBC API。
  5. 命令 -TextComponent的撤消/重做。
  6. 解释器 -RegEx(java.util.regex。)和SQL(java.sql。)API。
  7. 原型 -不确定是否100%clone()可以算在内,但是我认为方法可以用于此目的。

1
关于Flyweight模式:它可能与java.awtjava.swing包不同。实际上,它们共享几乎相同的内在属性,外在属性是它们以UI形式布置的不同UI组件。
维塔利

@NawaMan您说过5. Comand TextComponent的撤消/重做。我认为这是纪念品而不是命令。或两者都有。
斯廷普森猫

您能否在一个相关问题中帮助我-stackoverflow.com/questions/61284856/…。我在这个简单的示例中使用了命令模式,但是我不确定这是否是解决我的问题的正确方法。
汤姆·乔

42

RMI基于代理。

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

  1. 抽象工厂:注册驱动程序后,java.sql接口都会从JDBC JAR获得其具体实现。
  2. 生成器:java.lang.StringBuilder。
  3. 工厂方法:XML工厂等。
  4. 原型:也许是clone(),但我不确定是否要购买。
  5. 单例:java.lang.System
  6. 适配器:java.awt.event中的适配器类,例如WindowAdapter。
  7. 桥:java.util中的集合类。列表由ArrayList实现。
  8. 合成:java.awt。java.awt.Component + java.awt.Container
  9. 装饰器:遍历java.io包。
  10. 外观:ExternalContext充当执行Cookie,会话范围和类似操作的外观。
  11. Flyweight:整数,字符等。
  12. 代理:java.rmi包
  13. 责任链:Servlet过滤器
  14. 命令:Swing菜单项
  15. 解释器:在JDK中没有直接使用,但是JavaCC肯定会使用它。
  16. 迭代器:java.util.Iterator接口;没有比这更清楚的了。
  17. 介体:JMS?
  18. 纪念品:
  19. 观察者:java.util.Observer/Observable(虽然做得不好)
  20. 州:
  21. 战略:
  22. 模板:
  23. 游客:

我想不出Java中的23个例子中有10个,但是我看看明天是否可以做得更好。这就是编辑的目的。


28

抽象工厂模式在各个地方都有使用。例如DatagramSocketImplFactoryPreferencesFactory。还有更多---在Javadoc中搜索名称中带有“ Factory”一词的接口。

也有很多Factory模式的实例。


22

尽管我对此有点不满意,但Java XML API经常使用Factory。我的意思是看看这个:

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

...等等等等。

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


21

java.util.Collection#Iterator是Factory方法的一个很好的例子。根据您使用的Collection的具体子类,它将创建一个Iterator实现。因为创建的Factory超类(集合)和迭代器都是接口,所以有时将它与AbstractFactory混淆。可接受答案(BalusC)中AbstractFactory的大多数示例都是Factory的示例,Factory是工厂方法的简化版本,它不属于原始GoF模式。在Facory中,Factory类层次结构被折叠,并且工厂使用其他方式选择要退货的产品。

  • 抽象工厂

抽象工厂有多种工厂方法,每种方法创建不同的产品。一个工厂生产的产品打算一起使用(您的打印机和墨盒最好来自同一(抽象的)工厂)。正如上面答案中提到的,不同平台的AWT GUI组件家族就是一个例子(尽管其实现方式与Gof中描述的结构不同)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.