装饰模式使用

1. 装饰模式的概念

装饰模式:
在不改变接口的前提下,动态扩展对象的访问。	
动态继承,让类具有在运行期改变行为的能力。	
装饰模式,突出的是运行期增加行为,这和继承是不同的,
继承是在编译期增加行为。
强调:增强,新增行为

策略模式有如下的角色: 
顶层构件接口: 规范了接口的动作行为
抽象构件类 : 实现顶层构件并维护一个构件对象,将行为做分发
核心构件类 : 脱离于抽象构件的核心独立存在

2. 代码实现

顶层构件接口:

1
2
3
4
5
public interface Milk {
int getPrice();
String getName();
}

抽象构件类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 抽象构件角色,继承 milk
* 并内部维护一个 compoment 对象,负责做接口请求的转发
*/
public abstract class MilkDecorator implements Milk {

protected Milk compoment;

public MilkDecorator(Milk compoment) {
this.compoment = compoment;
}


@Override
public int getPrice() {
return compoment.getPrice();
}

@Override
public String getName() {
return compoment.getName();
}

}

核心构件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 核心构件
*/
public class PureMilk implements Milk {

@Override
public int getPrice() {
return 5;
}

@Override
public String getName() {
return "纯牛奶";
}
}

构件:

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

public class AppleMilk extends MilkDecorator {


public AppleMilk(Milk compoment) {
super(compoment);
}

@Override
public int getPrice() {
return super.getPrice() + 5;
}


@Override
public String getName() {
return super.getName() + " 加苹果 ";
}
}

public class PeachMilk extends MilkDecorator {

public PeachMilk(Milk compoment) {
super(compoment);
}


@Override
public int getPrice() {
return super.getPrice() + 10;
}


@Override
public String getName() {
return super.getName() + " 黄桃 ";
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void main(String[] args) {


//核心构件
Milk milk = new PureMilk();


Milk packageA = new AppleMilk(milk);


Milk iceMilkA = new IceMilk(packageA);


System.out.println(iceMilkA.getPrice() + " , " + iceMilkA.getName());


Milk packageB = new PeachMilk(iceMilkA);


System.out.println(packageB.getPrice() + " , " + packageB.getName());

}

执行结果:

10 , 纯牛奶 加苹果  加冰 
20 , 纯牛奶 加苹果  加冰  黄桃 

3. 优缺点分析

优点:
1. 装饰模式可以提供比继承更多地灵活性。
2. 可以通过一种动态的方式来扩展一个对象的功能,
    在运行时选择不同的装饰器,从而实现不同的行为。
缺点: 
1. 会产生很多的小对象(具体装饰类),增加了系统的复杂性。
2. 装饰模式比继承易于出错,排错也很困难,对于多次装饰的对象,
    调试时寻找错误可能需要逐级排查,较为烦琐。