auto commit
This commit is contained in:
407
notes/设计模式.md
407
notes/设计模式.md
@ -1,9 +1,31 @@
|
||||
<!-- GFM-TOC -->
|
||||
* [一、概述](#一概述)
|
||||
* [二、单例模式](#二单例模式)
|
||||
* [三、简单工厂](#三简单工厂)
|
||||
* [四、工厂方法模式](#四工厂方法模式)
|
||||
* [五、抽象工厂模式](#五抽象工厂模式)
|
||||
* [二、创建型](#二创建型)
|
||||
* [1. 单例模式](#1-单例模式)
|
||||
* [2. 简单工厂](#2-简单工厂)
|
||||
* [3. 工厂方法模式](#3-工厂方法模式)
|
||||
* [4. 抽象工厂模式](#4-抽象工厂模式)
|
||||
* [5. 生成器](#5-生成器)
|
||||
* [6. 原型模式](#6-原型模式)
|
||||
* [三、行为型](#三行为型)
|
||||
* [1. 责任链](#1-责任链)
|
||||
* [2. 命令模式](#2-命令模式)
|
||||
* [3. 解释器模式](#3-解释器模式)
|
||||
* [4. 迭代器](#4-迭代器)
|
||||
* [5. 中间人模式](#5-中间人模式)
|
||||
* [6. 备忘录模式](#6-备忘录模式)
|
||||
* [7. 观察者模式](#7-观察者模式)
|
||||
* [8. 策略模式](#8-策略模式)
|
||||
* [9. 模板方法](#9-模板方法)
|
||||
* [10. 访问者模式](#10-访问者模式)
|
||||
* [11. 空对象模式](#11-空对象模式)
|
||||
* [四、结构型](#四结构型)
|
||||
* [1. 适配器](#1-适配器)
|
||||
* [2. 桥接模式](#2-桥接模式)
|
||||
* [3. 组合模式](#3-组合模式)
|
||||
* [4. 装饰者模式](#4-装饰者模式)
|
||||
* [5. 蝇量模式](#5-蝇量模式)
|
||||
* [6. 动态代理](#6-动态代理)
|
||||
* [参考资料](#参考资料)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
@ -14,13 +36,15 @@
|
||||
|
||||
拥有设计模式词汇,在沟通时就能用更少的词汇来讨论,并且不需要了解底层细节。
|
||||
|
||||
# 二、单例模式
|
||||
# 二、创建型
|
||||
|
||||
## 意图
|
||||
## 1. 单例模式
|
||||
|
||||
确保一个类只有一个实例,并提供了一个全局访问点。
|
||||
### 意图
|
||||
|
||||
## 类图
|
||||
确保一个类只有一个实例,并提供该实例的全局访问点。
|
||||
|
||||
### 类图
|
||||
|
||||
使用一个私有构造函数、一个私有静态变量以及一个公有静态函数来实现。
|
||||
|
||||
@ -28,22 +52,9 @@
|
||||
|
||||
<div align="center"> <img src="../pics//db54db2f-82b2-4222-8d63-e49a8a7fc966.png"/> </div><br>
|
||||
|
||||
## 使用场景
|
||||
### 实现
|
||||
|
||||
- Logger Classes
|
||||
- Configuration Classes
|
||||
- Accesing resources in shared mode
|
||||
- Factories implemented as Singletons
|
||||
|
||||
## JDK 的使用
|
||||
|
||||
- [java.lang.Runtime#getRuntime()](http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#getRuntime%28%29)
|
||||
- [java.awt.Desktop#getDesktop()](http://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#getDesktop--)
|
||||
- [java.lang.System#getSecurityManager()](http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getSecurityManager--)
|
||||
|
||||
## 实现
|
||||
|
||||
### 懒汉式-线程不安全
|
||||
#### 懒汉式-线程不安全
|
||||
|
||||
以下实现中,私有静态变量 uniqueInstance 被延迟化实例化,这样做的好处是,如果没有用到该类,那么就不会实例化 uniqueInstance,从而节约资源。
|
||||
|
||||
@ -66,7 +77,7 @@ public class Singleton {
|
||||
}
|
||||
```
|
||||
|
||||
### 懒汉式-线程安全
|
||||
#### 懒汉式-线程安全
|
||||
|
||||
只需要对 getUniqueInstance() 方法加锁,那么在一个时间点只能有一个线程能够进入该方法,从而避免了对 uniqueInstance 进行多次实例化的问题。
|
||||
|
||||
@ -81,7 +92,7 @@ public static synchronized Singleton getUniqueInstance() {
|
||||
}
|
||||
```
|
||||
|
||||
### 饿汉式-线程安全
|
||||
#### 饿汉式-线程安全
|
||||
|
||||
线程不安全问题主要是由于 uniqueInstance 被实例化了多次,如果 uniqueInstance 采用直接实例化的话,就不会被实例化多次,也就不会产生线程不安全问题。但是直接实例化的方式也丢失了延迟实例化带来的节约资源的优势。
|
||||
|
||||
@ -89,11 +100,11 @@ public static synchronized Singleton getUniqueInstance() {
|
||||
private static Singleton uniqueInstance = new Singleton();
|
||||
```
|
||||
|
||||
### 双重校验锁-线程安全
|
||||
#### 双重校验锁-线程安全
|
||||
|
||||
uniqueInstance 只需要被实例化一次,之后就可以直接使用了。加锁操作只需要对实例化那部分的代码进行。也就是说,只有当 uniqueInstance 没有被实例化时,才需要进行加锁。
|
||||
|
||||
双重校验锁先判断 uniqueInstance 是否已经被初始化了,如果没有被实例化,那么才对实例化语句进行加锁。
|
||||
双重校验锁先判断 uniqueInstance 是否已经被实例化,如果没有被实例化,那么才对实例化语句进行加锁。
|
||||
|
||||
```java
|
||||
public class Singleton {
|
||||
@ -116,7 +127,7 @@ public class Singleton {
|
||||
}
|
||||
```
|
||||
|
||||
考虑下面的实现,也就是只使用了一个 if 语句。在 uniqueInstance == null 的情况下,如果两个线程同时执行 if 语句,那么两个线程就会同时进入 if 语句块内。虽然在 if 语句块内有加锁操作,但是两个线程都会执行 uniqueInstance = new Singleton(); 这条语句,只是早晚的问题,也就是说会进行两次实例化,从而产生了两个实例。因此必须使用双重校验锁,也就是需要使用两个 if 判断。
|
||||
考虑下面的实现,也就是只使用了一个 if 语句。在 uniqueInstance == null 的情况下,如果两个线程同时执行 if 语句,那么两个线程就会同时进入 if 语句块内。虽然在 if 语句块内有加锁操作,但是两个线程都会执行 uniqueInstance = new Singleton(); 这条语句,只是先后的问题,也就是说会进行两次实例化,从而产生了两个实例。因此必须使用双重校验锁,也就是需要使用两个 if 判断。
|
||||
|
||||
```java
|
||||
if (uniqueInstance == null) {
|
||||
@ -126,25 +137,69 @@ if (uniqueInstance == null) {
|
||||
}
|
||||
```
|
||||
|
||||
uniqueInstance 采用 volatile 关键字修饰也是很有必要的。
|
||||
uniqueInstance 采用 volatile 关键字修饰也是很有必要的。uniqueInstance = new Singleton(); 这段代码其实是分为三步执行。
|
||||
|
||||
uniqueInstance = new Singleton(); 这段代码其实是分为三步执行。
|
||||
1. 分配内存空间。
|
||||
2. 初始化对象。
|
||||
3. 将 uniqueInstance 指向分配的内存地址。
|
||||
|
||||
1. 分配内存空间。
|
||||
2. 初始化对象。
|
||||
3. 将 uniqueInstance 指向分配的内存地址。
|
||||
但是由于 JVM 具有指令重排的特性,有可能执行顺序变为了 1>3>2,这在单线程情况下自然是没有问题。但如果是多线程下,有可能获得是一个还没有被初始化的实例,以致于程序出错。
|
||||
|
||||
但是由于 JVM 具有指令重排的特性,有可能执行顺序变为了 1>3>2,这在单线程情况下自然是没有问题。但如果是多线程就有可能 B 线程获得是一个还没有被初始化的对象以致于程序出错。
|
||||
使用 volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。
|
||||
|
||||
所以使用 volatile 修饰的目的是禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。
|
||||
#### 枚举实现
|
||||
|
||||
# 三、简单工厂
|
||||
这是单例模式的最佳实践,它实现简单,并且在复杂的序列化或者反射攻击的时候,能够防止实例化多次。
|
||||
|
||||
## 意图
|
||||
```java
|
||||
public enum Singleton {
|
||||
uniqueInstance;
|
||||
}
|
||||
```
|
||||
|
||||
在创建一个对象时不向客户暴露内部细节;
|
||||
考虑以下单例模式的实现,该 Singleton 在每次序列化的时候都会创建一个新的实例,为了保证只创建一个实例,必须声明所有字段都是 transient,并且提供一个 readResolve() 方法。
|
||||
|
||||
## 类图
|
||||
```java
|
||||
public class Singleton implements Serializable{
|
||||
|
||||
private static Singleton uniqueInstance;
|
||||
|
||||
private Singleton() {
|
||||
}
|
||||
|
||||
public static synchronized Singleton getUniqueInstance() {
|
||||
if (uniqueInstance == null) {
|
||||
uniqueInstance = new Singleton();
|
||||
}
|
||||
return uniqueInstance;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
如果不使用枚举来实现单例模式,会出现反射攻击,因为通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public,然后调用构造函数从而实例化对象。如果要防止这种攻击,需要在构造函数中添加防止实例化第二个对象的代码。
|
||||
|
||||
从上面的讨论可以看出,解决序列化和反射攻击很麻烦,而枚举实现不会出现这两种问题,所以说枚举实现单例模式是最佳实践。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- Logger Classes
|
||||
- Configuration Classes
|
||||
- Accesing resources in shared mode
|
||||
- Factories implemented as Singletons
|
||||
|
||||
### JDK
|
||||
|
||||
- [java.lang.Runtime#getRuntime()](http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#getRuntime%28%29)
|
||||
- [java.awt.Desktop#getDesktop()](http://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#getDesktop--)
|
||||
- [java.lang.System#getSecurityManager()](http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getSecurityManager--)
|
||||
|
||||
## 2. 简单工厂
|
||||
|
||||
### 意图
|
||||
|
||||
在创建一个对象时不向客户暴露内部细节,并提供一个创建对象的通用接口。
|
||||
|
||||
### 类图
|
||||
|
||||
简单工厂不是设计模式,更像是一种编程习惯。它把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个子类来实例化。
|
||||
|
||||
@ -170,7 +225,7 @@ public class Client {
|
||||
}
|
||||
```
|
||||
|
||||
## 实现
|
||||
### 实现
|
||||
|
||||
```java
|
||||
public interface Product {
|
||||
@ -214,13 +269,13 @@ public class Client {
|
||||
}
|
||||
```
|
||||
|
||||
# 四、工厂方法模式
|
||||
## 3. 工厂方法模式
|
||||
|
||||
## 意图
|
||||
### 意图
|
||||
|
||||
定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化推迟到子类。
|
||||
|
||||
## 类图
|
||||
### 类图
|
||||
|
||||
在简单工厂中,创建对象的是另一个类,而在工厂方法中,是由子类来创建对象。
|
||||
|
||||
@ -228,7 +283,7 @@ public class Client {
|
||||
|
||||
<div align="center"> <img src="../pics//bf0ff9fc-467e-4a3f-8922-115ba2c55bde.png"/> </div><br>
|
||||
|
||||
## 实现
|
||||
### 实现
|
||||
|
||||
```java
|
||||
public abstract class Factory {
|
||||
@ -264,25 +319,35 @@ public class ConcreteFactory2 extends Factory {
|
||||
}
|
||||
```
|
||||
|
||||
# 五、抽象工厂模式
|
||||
### JDK
|
||||
|
||||
## 意图
|
||||
- [java.util.Calendar](http://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)
|
||||
- [java.util.ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)
|
||||
- [java.text.NumberFormat](http://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)
|
||||
- [java.nio.charset.Charset](http://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)
|
||||
- [java.net.URLStreamHandlerFactory](http://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html#createURLStreamHandler-java.lang.String-)
|
||||
- [java.util.EnumSet](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of-E-)
|
||||
- [javax.xml.bind.JAXBContext](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--)
|
||||
|
||||
## 4. 抽象工厂模式
|
||||
|
||||
### 意图
|
||||
|
||||
提供一个接口,用于创建 **相关的对象家族** 。
|
||||
|
||||
## 类图
|
||||
### 类图
|
||||
|
||||
<div align="center"> <img src="../pics//14cfe8d4-e31b-49e0-ac6a-6f4f7aa06ab6.png"/> </div><br>
|
||||
|
||||
抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂模式只是用于创建一个对象,这和抽象工厂模式有很大不同。
|
||||
|
||||
抽象工厂模式用到了工厂模式来创建单一对象,AbstractFactory 中的 createProductA 和 createProductB 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂模式的定义。
|
||||
抽象工厂模式用到了工厂模式来创建单一对象,AbstractFactory 中的 createProductA() 和 createProductB() 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂模式的定义。
|
||||
|
||||
至于创建对象的家族这一概念是在 Client 体现,Client 要通过 AbstractFactory 同时调用两个方法来创建出两个对象,在这里这两个对象就有很大的相关性,Client 需要同时创建出这两个对象。
|
||||
|
||||
从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory,而工厂模式使用了继承。
|
||||
|
||||
## 代码实现
|
||||
### 代码实现
|
||||
|
||||
```java
|
||||
public class AbstractProductA {
|
||||
@ -356,8 +421,252 @@ public class Client {
|
||||
}
|
||||
```
|
||||
|
||||
### JDK
|
||||
|
||||
- [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)
|
||||
- [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)
|
||||
- [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)
|
||||
|
||||
## 5. 生成器
|
||||
|
||||
### 意图
|
||||
|
||||
定义一个新的类来构造另一个类的实例,以创建一个复杂的对象。
|
||||
|
||||
它可以封装一个对象的构造过程,并允许按步骤构造。
|
||||
|
||||
### JDK
|
||||
|
||||
- [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)
|
||||
- [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-)
|
||||
- [java.lang.StringBuffer](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-)
|
||||
- [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html)
|
||||
- [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)
|
||||
|
||||
## 6. 原型模式
|
||||
|
||||
### 意图
|
||||
|
||||
使用原型实例指定要创建对象的类型;通过复制这个原型来创建新对象。
|
||||
|
||||
### JDK
|
||||
|
||||
- [java.lang.Object#clone()](http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#clone%28%29)
|
||||
|
||||
# 三、行为型
|
||||
|
||||
## 1. 责任链
|
||||
|
||||
### 意图
|
||||
|
||||
避免将请求的发送者附加到其接收者,从而使其它对象也可以处理请求;将请求以对象的方式发送到链上直到请求被处理完毕。
|
||||
|
||||
### JDK
|
||||
|
||||
- [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29)
|
||||
- [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html)
|
||||
- [javax.servlet.Filter#doFilter()](http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-)
|
||||
|
||||
## 2. 命令模式
|
||||
|
||||
### 意图
|
||||
|
||||
将命令封装进对象中;允许使用命令对象对客户对象进行参数化;允许将命令对象存放到队列中。
|
||||
|
||||
### JDK
|
||||
|
||||
- [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)
|
||||
- [Netflix Hystrix](https://github.com/Netflix/Hystrix/wiki)
|
||||
- [javax.swing.Action](http://docs.oracle.com/javase/8/docs/api/javax/swing/Action.html)
|
||||
|
||||
## 3. 解释器模式
|
||||
|
||||
### 意图
|
||||
|
||||
为语言创建解释器,通常由语言的语法和语法分析来定义。
|
||||
|
||||
### JDK
|
||||
|
||||
- [java.util.Pattern](http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html)
|
||||
- [java.text.Normalizer](http://docs.oracle.com/javase/8/docs/api/java/text/Normalizer.html)
|
||||
- All subclasses of [java.text.Format](http://docs.oracle.com/javase/8/docs/api/java/text/Format.html)
|
||||
- [javax.el.ELResolver](http://docs.oracle.com/javaee/7/api/javax/el/ELResolver.html)
|
||||
|
||||
## 4. 迭代器
|
||||
|
||||
### 意图
|
||||
|
||||
提供一种一致的访问聚合对象元素的方法,并且不暴露聚合对象的内部表示。
|
||||
|
||||
### JDK
|
||||
|
||||
- [java.util.Iterator](http://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html)
|
||||
- [java.util.Enumeration](http://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html)
|
||||
|
||||
## 5. 中间人模式
|
||||
|
||||
### 意图
|
||||
|
||||
使用中间人对象来封装对象之间的交互。中间人模式可以降低交互对象之间的耦合程度。
|
||||
|
||||
### JDK
|
||||
|
||||
- All scheduleXXX() methods of [java.util.Timer](http://docs.oracle.com/javase/8/docs/api/java/util/Timer.html)
|
||||
- [java.util.concurrent.Executor#execute()](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable-)
|
||||
- submit() and invokeXXX() methods of [java.util.concurrent.ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html)
|
||||
- scheduleXXX() methods of [java.util.concurrent.ScheduledExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html)
|
||||
- [java.lang.reflect.Method#invoke()](http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#invoke-java.lang.Object-java.lang.Object...-)
|
||||
|
||||
## 6. 备忘录模式
|
||||
|
||||
### 意图
|
||||
|
||||
在不违反封装的情况下获得对象的内部状态,从而在需要时可以将对象恢复到最初状态。
|
||||
|
||||
### JDK
|
||||
|
||||
- [java.util.Date](http://docs.oracle.com/javase/8/docs/api/java/util/Date.html)
|
||||
|
||||
## 7. 观察者模式
|
||||
|
||||
### 意图
|
||||
|
||||
定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知并且自动更新状态。
|
||||
|
||||
### JDK
|
||||
|
||||
- [java.util.Observer](http://docs.oracle.com/javase/8/docs/api/java/util/Observer.html)
|
||||
- [java.util.EventListener](http://docs.oracle.com/javase/8/docs/api/java/util/EventListener.html)
|
||||
- [javax.servlet.http.HttpSessionBindingListener](http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionBindingListener.html)
|
||||
- [RxJava](https://github.com/ReactiveX/RxJava)
|
||||
|
||||
## 8. 策略模式
|
||||
|
||||
### 意图
|
||||
|
||||
定义一系列算法,封装每个算法,并使它们可以互换。策略可以让算法独立于使用它的客户端。
|
||||
|
||||
### JDK
|
||||
|
||||
- java.util.Comparator#compare()
|
||||
- javax.servlet.http.HttpServlet
|
||||
- javax.servlet.Filter#doFilter()
|
||||
|
||||
## 9. 模板方法
|
||||
|
||||
### 意图
|
||||
|
||||
定义算法框架,并将一些步骤的实现延迟到子类。通过模板方法,子类可以重新定义算法的某些步骤,而不用改变算法的结构。
|
||||
|
||||
### JDK
|
||||
|
||||
- java.util.Collections#sort()
|
||||
- java.io.InputStream#skip()
|
||||
- java.io.InputStream#read()
|
||||
- java.util.AbstractList#indexOf()
|
||||
|
||||
## 10. 访问者模式
|
||||
|
||||
### 意图
|
||||
|
||||
提供便捷的维护方式来操作一组对象。它使你在不改变操作对象的前提下,可以修改或扩展对象的行为。
|
||||
|
||||
例如集合,它可以包含不同类型的元素,访问者模式允许在不知道具体元素类型的前提下对集合元素进行一些操作。
|
||||
|
||||
### JDK
|
||||
|
||||
- javax.lang.model.element.Element and javax.lang.model.element.ElementVisitor
|
||||
- javax.lang.model.type.TypeMirror and javax.lang.model.type.TypeVisitor
|
||||
|
||||
## 11. 空对象模式
|
||||
|
||||
使用什么都不做的空对象来替代 NULL。
|
||||
|
||||
# 四、结构型
|
||||
|
||||
## 1. 适配器
|
||||
|
||||
### 意图
|
||||
|
||||
把一个类接口转换成另一个用户需要的接口。
|
||||
|
||||
### JDK
|
||||
|
||||
- [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)
|
||||
- [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-)
|
||||
- [java.util.Collections#enumeration()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-)
|
||||
- [javax.xml.bind.annotation.adapters.XMLAdapter](http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-)
|
||||
|
||||
## 2. 桥接模式
|
||||
|
||||
### 意图
|
||||
|
||||
将抽象与实现分离开来,使它们可以独立变化。
|
||||
|
||||
### JDK
|
||||
|
||||
- AWT (It provides an abstraction layer which maps onto the native OS the windowing support.)
|
||||
- JDBC
|
||||
|
||||
## 3. 组合模式
|
||||
|
||||
### 意图
|
||||
|
||||
将对象组合成树形结构来表示整体-部分层次关系,允许用户以相同的方式处理单独对象和组合对象。
|
||||
|
||||
### JDK
|
||||
|
||||
- javax.swing.JComponent#add(Component)
|
||||
- java.awt.Container#add(Component)
|
||||
- java.util.Map#putAll(Map)
|
||||
- java.util.List#addAll(Collection)
|
||||
- java.util.Set#addAll(Collection)
|
||||
|
||||
## 4. 装饰者模式
|
||||
|
||||
### 意图
|
||||
|
||||
为对象动态添加功能。
|
||||
|
||||
### JDK
|
||||
|
||||
- java.io.BufferedInputStream(InputStream)
|
||||
- java.io.DataInputStream(InputStream)
|
||||
- java.io.BufferedOutputStream(OutputStream)
|
||||
- java.util.zip.ZipOutputStream(OutputStream)
|
||||
- java.util.Collections#checked[List|Map|Set|SortedSet|SortedMap]()
|
||||
|
||||
## 5. 蝇量模式
|
||||
|
||||
### 意图
|
||||
|
||||
利用共享的方式来支持大量的对象,这些对象一部分内部状态是相同的,而另一份状态可以变化。
|
||||
|
||||
### JDK
|
||||
|
||||
Java 利用缓存来加速大量小对象的访问时间。
|
||||
|
||||
- java.lang.Integer#valueOf(int)
|
||||
- java.lang.Boolean#valueOf(boolean)
|
||||
- java.lang.Byte#valueOf(byte)
|
||||
- java.lang.Character#valueOf(char)
|
||||
|
||||
## 6. 动态代理
|
||||
|
||||
### 意图
|
||||
|
||||
提供一个占位符来控制对象的访问。
|
||||
|
||||
代理可以是一些轻量级的对象,它控制着对重量级对象的访问,只有在真正实例化这些重量级对象时才会去实例化它。
|
||||
|
||||
### JDK
|
||||
|
||||
- java.lang.reflect.Proxy
|
||||
- RMI
|
||||
|
||||
# 参考资料
|
||||
|
||||
- 弗里曼. Head First 设计模式 [M]. 中国电力出版社, 2007.
|
||||
- [Design Patterns](http://www.oodesign.com/)
|
||||
- [Design patterns implemented in Java](http://java-design-patterns.com/)
|
||||
- [The breakdown of design patterns in JDK](http://www.programering.com/a/MTNxAzMwATY.html)
|
||||
|
Reference in New Issue
Block a user