每天一个设计模式:装饰者模式 - Sanarous的博客

每天一个设计模式:装饰者模式

装饰者模式

1、意图

动态的给一个对象添加额外的功能,装饰者模式是一种用于代替继承的技术,无须通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。

2、适用环境

  1. 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
  2. 处理那些可以撤销的职责
  3. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类的数量爆炸增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

3、参与者

  1. Component(抽象构件角色)

    真实对象和装饰对象有相同的接口,这样,客户端对象就能够以与真实对象相同的方式同装饰对象进行交互。

  2. ConcreteComponent(具体构件角色,即真实对象)

    IO流中的FileInputStream、FileOutputStream

  3. Decorator(装饰角色)

    持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象。这样,就能在真实对象调用前后增加新的功能。

  4. ConcreteDecorator(具体装饰角色)

    负责给构件对象增加新的责任。

4、类图

5、涉及角色

  1. 抽象组件:定义一个抽象接口,来规范准备附加功能的类。
  2. 具体组件:将要被附加功能的类,实现抽象构件角色接口。
  3. 抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口。
  4. 具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。

6、代码举例

对已有的业务逻辑进一步的封装,使其增加额外的功能,如Java中的IO流就使用了装饰者模式,用户在使用的时候,可以任意组装,达到自己想要的效果。 举个栗子,我想吃三明治,首先我需要一根大大的香肠,我喜欢吃奶油,在香肠上面加一点奶油,再放一点蔬菜,最后再用两片面包夹一下,很丰盛的一顿午饭,营养又健康。那我们应该怎么来写代码呢? 首先,我们需要写一个Food类,让其他所有食物都来继承这个类,看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Food {

private String food_name;

public Food() {
}

public Food(String food_name) {
this.food_name = food_name;
}

public String make() {
return food_name;
};
}

代码很简单,我就不解释了,然后我们写几个子类继承它:

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
//面包类
public class Bread extends Food {

private Food basic_food;

public Bread(Food basic_food) {
this.basic_food = basic_food;
}

public String make() {
//加入子类实现的具体逻辑
return basic_food.make()+"+面包";
}
}

//奶油类
public class Cream extends Food {

private Food basic_food;

public Cream(Food basic_food) {
this.basic_food = basic_food;
}

public String make() {
//加入子类实现的具体逻辑
return basic_food.make()+"+奶油";
}
}

//蔬菜类
public class Vegetable extends Food {

private Food basic_food;

public Vegetable(Food basic_food) {
this.basic_food = basic_food;
}

public String make() {
//加入子类实现的具体逻辑
return basic_food.make()+"+蔬菜";
}

}

这几个类都是差不多的,构造方法传入一个Food类型的参数,然后在make方法中加入一些自己的逻辑,如果你还是看不懂为什么这么写,不急,你看看我的Test类是怎么写的,一看你就明白了 。

1
2
3
4
5
6
public class Test {
public static void main(String[] args) {
Food food = new Bread(new Vegetable(new Cream(new Food("香肠"))));
System.out.println(food.make());
}
}

如果用继承去实现的话,会产生什么样的结果呢?

首先,肯定是需要创建一个Food类,然后去创建Food类的子类叫香肠奶油蔬菜三明治,但是如果我每天都不想吃同一种菜,那么每天都需要创建一个子类去继承Food类,这样下去肯定是会产生子类爆炸的。而利用装饰者模式,比如我个人就偏爱吃蔬菜、奶油、鸡蛋、面包等这几个具体的类,那么我们只需要对这几种类进行继承或者实现即可,而不用单独去一一创建组合的子类,具体吃啥则有我们自己对基本food进行自由装饰。

如果这篇文章对您很有帮助,不妨
-------------    本文结束  感谢您的阅读    -------------
0%