设计模式(一)

  |  

归类设计模式

大致按照模式的应用目标分类,设计模式可以分为创建型模式、结构型模式和行为型模式。

  1. 创建型模式,是对对象创建过程的各种问题和解决方案的总结。

    • 包括各种工厂模式(Factory、Abstract Factory)、单例模式(Singleton)、构建器模式(Builder)、原型模式(ProtoType)。
  2. 结构型模式,是针对软件设计结构的总结,关注于类、对象继承、组合方式的实践经验。

    • 常见的结构型模式,包括桥接模式(Bridge)、适配器模式(Adapter)、装饰者模式(Decorator)、代理模式(Proxy)、组合模式(Composite)、外观模式(Facade)、享元模式(Flyweight)等。
  3. 行为型模式,是从类或对象之间交互、职责划分等角度总结的模式。

    • 比较常见的行为型模式有策略模式(Strategy)、解释器模式(Interpreter)、命令模式(Command)、观察者模式(Observer)、迭代器模式(Iterator)、模板方法模式(Template Method)、访问者模式(Visitor)。

装饰者模式

  • 识别装饰器模式,可以通过识别类设计特征来进行判断,也就是其类构造函数以相同的抽象类或者接口为输入参数。

我们知道 InputStream 是一个抽象类,标准类库中提供了 FileInputStream、ByteArrayInputStream 等各种不同的子类,分别从不同角度对 InputStream 进行了功能扩展,这是典型的装饰器模式应用案例。

  • 例如,BufferedInputStream 经过包装,为输入流过程增加缓存,类似这种装饰器还可以多次嵌套,不断地增加不同层次的功能。

1
public BufferedInputStream(InputStream in)

因为装饰器模式本质上是包装同类型实例,我们对目标对象的调用,往往会通过包装类覆盖过的方法,迂回调用被包装的实例,这就可以很自然地实现增加额外逻辑的目的,也就是所谓的“装饰”。


工厂模式

工厂模式,在我们的代码中随处可见,我举个相对不同的 API 设计实践。比如,JDK 最新版本中 HTTP/2 Client API,下面这个创建 HttpRequest 的过程,就是典型的构建器模式(Builder),通常会被实现成fluent 风格的 API,也有人叫它方法链。

1
2
3
4
5
6
7
HttpRequest request = HttpRequest.newBuilder(new URI(uri))
.header(headerAlice, valueAlice)
.headers(headerBob, value1Bob,
headerCarl, valueCarl,
headerBob, value2Bob)
.GET()
.build();
  • 使用构建器模式,可以比较优雅地解决构建复杂对象的麻烦,这里的“复杂”是指类似需要输入的参数组合较多;
  • 如果用构造函数,我们往往需要为每一种可能的输入参数组合实现相应的构造函数,一系列复杂的构造函数会让代码阅读性和可维护性变得很差。

代码简单示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public class BeanFactory {

/**
* 编写工厂类的四个基本步骤:
* 1.声明一个私有的工厂对象引用
* 2.把构造方法私有化
* 3.使用静态代码块初始化
* 4.提供共有的静态的方法,获取工厂类对象的引用
*/
// 1.声明一个私有的工厂对象引用
private static BeanFactory beanFactory= null;
private static Properties prop;

// 2.把构造方法私有化
private BeanFactory(){

}

// 3.使用静态代码块初始化
static{
beanFactory = new BeanFactory();

//通过加载本类的字节码对象,然后加载并获得输入流
InputStream inStream = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
prop = new Properties();
try {
//读取properties文件的属性
prop.load(inStream);
} catch (IOException e) {
e.printStackTrace();
}
}

// 4.提供共有的静态的方法,获取工厂类对象的引用
public static BeanFactory getBeanFactory(){
return beanFactory;
}

/**
* 工厂创建对象的改良版本:
* 1.通过配置文件的方式,解决了对具体实现的依赖
* 2.如果需要修改为其它的实现类对象,不需要再修改java代码,只需要修改配置文件即可
* 3.这里可以统一创建我们需要的全部目标对象
*
*/
public Object getInstance(String beanName){
String className = (String) prop.get(beanName);
Object result = null;
try {
result = Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}

  • properties文件
    1
    CUSTOMERDAO=com.dao.impl.CustomerDaoImpl

Spring的IOC思想也是用到了工厂模式,之前对于对象的创建,由在程序代码中主动new对象,转变为由工厂创建提供,我们使用的地方被动接收的方式。称为控制反转。

  • 主动创建对象
  • 被动获取对象

框架使用的模式

简要看看主流开源框架,如 Spring 等如何在 API 设计中使用设计模式。你至少要有个大体的印象,如:

  • BeanFactory和ApplicationContext应用了工厂模式。

  • Bean 的创建中,Spring 也为不同 scope 定义的对象,提供了单例和原型等模式实现。

  • AOP 领域则是使用了代理模式、装饰器模式、适配器模式等。

  • 各种事件监听器,是观察者模式的典型应用。

  • 类似 JdbcTemplate 等则是应用了模板模式

Copyright © 2018 - 2020 Kuanger All Rights Reserved.

访客数 : | 访问量 :