Java设计模式——装饰模式(Decorator Pattern)
1 装饰者模式定义
装饰模式是一种常见的模式,其定义如下:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰者模式相比生成的子类更加灵活。
装饰者模式的通用类图:
-
Component抽象构件
Component是一个接口或者是抽象类,就是最核心的对象。
-
ConcreteComponent具体构件
ConcreteComponent是最核心的、最原始、最基本的接口或者抽象的实现,你要具体装饰的就是它。
-
Decorator装饰角色
一般是一个抽象类,实现接口或者抽象方法(里面不一定有抽象方法),在它的属性里面必然存在一个private变量指向Component抽象构件
-
具体装饰角色
ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,添加具体的你所需要的装饰。
2 具体使用装饰者模式
使用场景:士兵装配消音器与红外线进行射击(注意:这里确实可以使用继承Gun类来实现功能,但是如果继续增加需求或者对装配的顺序进行改变,就意味着需要写新的子类,这样就会导致类爆炸的情况,所以定义装饰类来装饰,灵活性会有很大的提高
)
Gun类(Component抽象构件)
public abstract class Gun {
public abstract void shot();
}
HandGun类(ConcreteComponent具体构件)
public class HandGun extends Gun {
@Override
public void shot() {
System.out.println("射出一颗手枪子弹");
}
}
Decorator类(Decorator装饰角色)
public abstract class Decorator extends Gun {
private Gun gun;
public Decorator(Gun gun){
this.gun = gun;
}
@Override
public void shot() {
gun.shot();
}
}
HandGun装备红外线(ConcreteDecoratorA)
public class InfraredDecorator extends Decorator {
public InfraredDecorator(Gun gun) {
super(gun);
}
@Override
public void shot() {
System.out.println("装备红外线,精准度增加");
super.shot();
}
}
HandGun装备消音器(ConcreteDecoratorB)
public class SilencerDecorator extends Decorator {
public SilencerDecorator(Gun gun) {
super(gun);
}
@Override
public void shot() {
System.out.println("装备消音器,射击没有声音");
super.shot();
}
}
Soldier类
public class Soldier {
public static void main(String[] args) {
Gun gun = new HandGun();
//可以增加、删除、改变顺序等进行组合。与子类不同的是,子类实现这些都需要单独写实现类
gun = new InfraredDecorator(gun);
gun = new SilencerDecorator(gun);
gun.shot();
}
}
3 装饰模式的应用
3.1 装饰模式的优点
- 装饰类和被装饰类可以独立发展,而不会相互耦合。也就是,Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能,而Decorator也不用知道具体的构件。
- 装饰模式是继承方式的一个替代方案。
- 装饰模式可以动态的扩展一个实现类的功能。
3.2 装饰模式的缺点
对于装饰模式来说,多层的装饰是比较复杂的。一层层的装饰,到最后出现错误,就需要一层层的去检查,所以应该尽量减少装饰类的数量,降低系统的复杂度。
3.3 装饰模式的使用场景
- 需要扩展一个类的功能,或给一个类增加附加功能
- 需要动态地给一个对象增加功能,这些功能可以动态的撤销
- 需要为一批兄弟类进行改装或加装功能,首选装饰模式