Decorator Pattern 对象结构型模式
意图
动态地给一个对象添加一些额外的职责。就增加功能而言,Decorator 模式比生成子类更加灵活
结构
其中:
- Component 定义一个对象接口,可以给这些对象动态地添加职责
- ConcreteComponent 定义一个对象,可以给这个对象添加一些职责
- Decorator 维持一个指向 Component 对象的指针,并定义一个与 Component 接口一致的接口
- ConcreteDecorator 向组件添加职责
适用性
Decorator 模式适用于:
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
- 处理那些可以撤销的职责
- 当不能采用生成子类的方式进行扩充时,一种情况是,可能有大量独立的拓展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是,由于类定义被隐藏,或类定义不能用于生成子类
例子 1
某咖啡店当卖咖啡时,可以根据顾客的要求在其中加入各种配料,咖啡店会根据所加入的配料来计算费用。咖啡店所供应的咖啡及配料的种类和价格如下表所示
现采用装饰器模式来实现计算费用的功能,得到如下类图
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
import java.util.*;
abstract class Beverage { // 饮料
String description = "Unknown Beverage";
public String getDescription() { return description; }
public abstract int cost();
}
abstract class CondimentDecorator extends Beverage { // 配料
Beverage beverage;
}
class Espresso extends Beverage { // 蒸馏咖啡
private final int ESPRESSO_PRICE = 25;
public Espresso() { description = "Espresso"; }
public int cost() { return ESPRESSO_PRICE; }
}
class DarkRoast extends Beverage { // 深度烘焙咖啡
private final int DARKROAST_PRICE = 20;
public DarkRoast() { description = "DarkRoast"; }
public int cost() { rcturn DARKROAST PRICE; }
}
class Mocha extends CondimentDecorator { // 摩卡
private final int MOCHA_PRICE = 10;
public Mocha (Beverage beverage) { this.beverage = beverage; }
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
public int cost() { return MOCHA_PRICE + beverage.cost(); }
}
class Whip extends CondimentDecorator { // 奶泡
private final int WHIP_PRICE = 8;
public Whip (Beverage beverage) { this.beverage = beverage; }
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
public int cost() { return WHIP_PRICE + beverage.cost(); }
}
public class Coffee {
public static void main(String args[]) {
Beverage beverage = new DarkRoast();
beverage = new Mocha(beverage);
beverage = new Whip(beverage);
System.out.println(beverage.getDescription() +" ¥"+ beverage.cost());
}
}
例子 2
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
57
58
59
60
61
62
63
64
65
public class DecoratorPattern {
public static void main(String[] args) {
Person p = new Student("Mike");
p.Operation();
System.out.println("\n--------------------");
p = new DecoratorA(p);
p.Operation();
System.out.println("\n--------------------");
p = new DecoratorB(p);
p.Operation();
// No.2
Person p2 = new DecoratorB(new Student("Jane"));
}
}
abstract class Person{
protected String name;
public abstract void Operation();
}
class Student extends Person{
public Student(String name){
this.name = name;
}
@Override
public void Operation(){
System.out.print(name + " Study");
}
}
abstract class Decorator extends Person{
protected Person person;
}
class DecoratorA extends Decorator{
public DecoratorA(Person person){
this.person = person;
}
@Override
public void Operation() {
person.Operation();
System.out.print(" Play");
}
}
class DecoratorB extends Decorator{
public DecoratorB(Person person){
this.person = person;
}
@Override
public void Operation() {
person.Operation();
System.out.print(" Exam");
}
}