设计模式--04.装饰者模式

在23种设计模式中,装饰者模式在游戏开发的过程中,使用的很是频繁。因为这个设计模式,把所有的业务的逻辑封装的对应的实体类中,从而为主流程减负了。首先看下一个应用场景

装饰者模式的应用

我们都知道有一款经典游戏90坦克,这个游戏中,玩家坦克来操作坦克打击AI敌人,在没打死一个红色坦克就会掉下来一个装备,这个装备可以提升移动速度,增加攻击力。

我们首先定义玩家坦克是player对象,再定义几个特别的装备,增加速度,增加生命,增加攻击力。对于这个场景,可以定制一下几个方法:

1
2
3
4
5

void addSpeed(Player player);
void addLife(Player player);
void addAttack(Player player);

这个方法定下来,就可以设计我们的程序,怎么设计呢? 我们可以设计一个最简单的设计,写一个静态的帮助类,代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
public class EquipmentHelper{
public void addSpeed(Player player){

}
public void addLife(Player player){

}
public void addAttack(Player player){

}

}

这个写完之后,我们们觉是可以实现我们的功能的?但是我们在条用的时候,是不是判断的逻辑比较多?如果类型比较多的时候,我们的系统就很难再维护了。

1
2
3
4
5
6
7
if(equipment is Speed){
equipmentHelper.addSpeed(player);
}
if(equipment is Life){
equipmentHelper.addLife(player);
}
....

这个一看,这样做问题出在哪里?
这个破坏了我们的player的对象,违反了OOP中的“对扩展开放,对修改关闭”的原则。

对于这个问题,我们可以用多态的方法进行,把需要抽象一个装备的基类,在基类中只有一个方法addProperty,然后就子类可以自己实现的装饰方法。整个装备类的实现如下:

装饰者模式

然后我们再调用的时候就省了if逻辑的判断:

1
2
3
4
5

public void equip(BaseEquipment equipment){
equipment.addProperty(player);
}

我们对上面的方法在进行优化,就是我们今天说的装饰者模式。

装饰者实现流程图

装饰者模式

装饰者实现逻辑

经过上面的分析,我们可以使用代码来表示我们的设计。

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

public abstract class Element {
public abstract String getEquipment();
}

public class Tank extends Element {
@Override
public String getEquipment() {
return "我是一辆坦克";
}
}

public abstract class BaseEquipment extends Element{

}


public class AttackEquipment extends BaseEquipment {
private Element element;
public AttackEquipment(Element element){
this.element=element;
}
@Override
public String getEquipment() {
return element.getEquipment()+",增加攻击力";
}
}

public class SpeedEquipment extends BaseEquipment{
private Element element;
public SpeedEquipment(Element element){
this.element=element;
}
@Override
public String getEquipment() {
return element.getEquipment()+",增加速度";
}
}


public class LifeEquipment extends BaseEquipment{
private Element element;
public LifeEquipment(Element element){
this.element=element;
}
@Override
public String getEquipment() {
return element.getEquipment()+",增加生命";
}
}

在最终的调用的时候,我们需要什么装备,就可以直接使用。调用如下:

1
2
3
4
5
6
Element tank = new Tank();
tank = new LifeEquipment(tank);
tank = new AttackEquipment(tank);
tank = new SpeedEquipment(tank);
System.out.println(tank.getEquipment());

运行结果:

1
我是一辆坦克,增加生命,增加攻击力,增加速度

Java中的装饰者模式的使用

在Java 中,IO的实现逻辑就是装饰者模式 ,首先看下IO的逻辑类图:

装饰者模式

1
2
3
4
InputStream dataStream = ClassLoader.getSystemResourceAsStream("");
dataStream = new BufferedInputStream(dataStream);
dataStream = new DataInputStream(dataStream);
dataStream = new LineNumberInputStream(dataStream);

对于Java中的IO缺点也有,会生成很多的小类,导致调用的时候不知道怎么去使用。知道了装饰者模式,我们就可以更好的使用IO的类。