一、概述
装饰模式可以在不改变一个对象本身功能的基础上增强或增加某些功能,举个例子,就相当于武侠小说里的内功,同样都是降龙十八掌,因为降龙十八掌属于外功,所以可能学了九阳真经的人和没有学九阳真经的人使用起来的威力必然是不相同的。
就好像倚天屠龙记里,阳顶天的乾坤大挪移必然没有张无忌的厉害。
正经一点的解释是这样子的:
装饰模式(Decorator Pattern):动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。
装饰模式是一种用于替代继承的技术,它通过一种无须定义子类的方式来给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系。在装饰模式中引入了装饰类,在装饰类中既可以调用待装饰的原有类的方法,还可以增加新的方法,以扩充原有类的功能。
这也应证了设计模式七大原则中的“合成复用原则”
二、角色职责与UML图
2.1角色与职责
Component(抽象构件)
- 它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
ConcreteComponent(具体构件)
- 它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。
Decorator(抽象装饰类)
- 它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
ConcreteDecorator(具体装饰类)
- 它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。
2.2 UML图
三、示例
就以武功为例,进行演示。
创建一个功夫类作为抽象构件,其中定义需要增强的方法
/**
* 抽象构件:定义行为
* @author ZhongJing </p>
*/
public abstract class GongFu {
public abstract int attack();
}
创建具体构件,降龙十八掌,拥有具体的行为
/**
* 具体构件:拥有自己的行为
* @author ZhongJing </p>
*/
public class XiangLongShiBaZhang extends GongFu{
@Override
public int attack() {
return 20;
}
}
创建抽象装饰器,内功,其中维护一个抽象构件,利用动态绑定就可以增强所有的继承自抽象构件的具体构件类中指定要增强的方法
/**
* 抽象装饰类:继承了抽象构件,并且内部维护一个抽象构件的对象
* @author ZhongJing </p>
*/
public class NeiGongDecorator extends GongFu {
private GongFu gongFu;
public NeiGongDecorator(GongFu gongFu) {
this.gongFu = gongFu;
}
public GongFu getGongFu() {
return gongFu;
}
public void setGongFu(GongFu gongFu) {
this.gongFu = gongFu;
}
@Override
public int attack() {
return gongFu.attack();
}
}
创建具体装饰器北冥神功,对某个具体构件的功能进行增强
/**
* 具体装饰类:负责增强构件的功能或给构件增加新的功能。
* @author ZhongJing </p>
*/
public class BeiMingDecorator extends NeiGongDecorator{
public BeiMingDecorator(GongFu gongFu) {
super(gongFu);
}
@Override
public int attack() {
// 具体构件原本的行为
int attack = super.attack();
// 具体装饰类增强了具体构件的行为
attack *= 100;
System.out.println("学习北冥神功,战斗力✖️100");
return attack;
}
}
创建一个测试类来测试一下我们的代码:
/**
* @author ZhongJing </p>
*/
public class MainTest {
public static void main(String[] args) {
XiangLongShiBaZhang xiangLongShiBaZhang = new XiangLongShiBaZhang();
System.out.println("降龙十八掌的伤害:" + xiangLongShiBaZhang.attack());
BeiMingDecorator beiMingDecorator = new BeiMingDecorator(xiangLongShiBaZhang);
System.out.println("学习北冥神功后降龙十八掌的伤害:" + beiMingDecorator.attack());
}
}
运行结果如下:
降龙十八掌的伤害:20
学习北冥神功,战斗力✖️100
学习北冥神功后降龙十八掌的伤害:2000