这篇博客我们来继续讲结构型模式,上一篇的适配器模式,如果读者有看过的话,应该会知道结构型模式关键还是在于类的继承,接口的实现。互相组合来实现我们想要的代码结构。那装饰器模式又是一个怎么样的存在呢?
我们先从之前的概念讲起来,假如有这么一个类class1,它的方法有function1,function2。然后我们想除了想用这2个方法之外呢,还想用function3。那我们可以写一个子类class2,用class2来继承这个父类class1。在class2中加上function3。这样我们就可以只需要新建一个子类class2。就可以调用这3个方法了。恩,挺好的。然而第二天,你想用function4。但是不想用function3了。想了下,没问题,那我再新建一个子类class3。用它来继承父类class1。加上function4。当你写完的时候是不是觉得有点做重复工作啊,这样我不是每天都要写一个类吗?装饰器模式就可以帮你大忙了。
为了更好的描述装饰器模式,我们来举一个煲汤的例子。平时工作日没空煮菜吃。到了周末,博主最喜欢去买筒骨回来煲骨头汤了。
那我们先来写一个煲汤的接口吧。
public interface Ibaotang {
/**
* 往水里放筒骨的方法
* 统称为放材料
*/
public void fangcailiao();
}
好了,接口写好了。我们在写一个煲汤的类去实现接口吧。
public class baotang implements Ibaotang{
@Override
public void fangcailiao() {
System.out.println("往水里放筒骨,开始煲汤");
}
}
这样,就可以煲筒骨汤了,可是博主我还喜欢放玉米和筒骨一起,这样煲出来的汤又甜又香。来吧,我们写一个加玉米的类。
/**
* 加玉米的“装饰”
* @author yidongming
*
*/
public class yumi implements Ibaotang{
private Ibaotang ibaotang;
public yumi(Ibaotang ibaotang){
this.ibaotang = ibaotang;
}
@Override
public void fangcailiao() {
System.out.println("往水里加点玉米");
ibaotang.fangcailiao();
}
}
这个玉米的类也实现了煲汤的接口。但是重写的方法里面带上了ibaotang的fangcailiao方法。自己也完成了加玉米的操作。我们来测试看看怎么调用吧。
public class baotangtest {
public static void main(String[] args) {
Ibaotang ibt = new baotang();
Ibaotang ym = new yumi(ibt);
ym.fangcailiao();
}
}
输出结果:
往水里加点玉米
往水里放筒骨,开始煲汤
这就完成了我们加玉米的操作了。可能看到这里还不是很通透。那我们再加点佐料吧,汤总要点盐吧?我们来继续添加加盐的类。
public class jiayan implements Ibaotang{
private Ibaotang ibaotang;
public jiayan(Ibaotang ibaotang){
this.ibaotang = ibaotang;
}
@Override
public void fangcailiao() {
System.out.println("加点盐,料酒。");
ibaotang.fangcailiao();
}
}
加盐的类和加玉米的类几乎一样。我们直接看调用吧。
public class baotangtest {
/*public static void main(String[] args) {
Ibaotang ibt = new baotang();
Ibaotang ym = new yumi(ibt);
ym.fangcailiao();
}*/
public static void main(String[] args) {
Ibaotang ibt = new baotang();
Ibaotang ym = new yumi(ibt);
Ibaotang jiayan = new jiayan(ym);
jiayan.fangcailiao();
}
}
加点盐,料酒。
往水里加点玉米
往水里放筒骨,开始煲汤
可以看的到,我们调用的方法也是一样的。这样就完成了装饰器模式了。你可以再多次添加不同的装饰器的类。你还可以加一个胡萝卜类,淮山类,煲你想要的汤。更重要的事。你还可以调整加的顺序,甚至是加的次数。灵活多变。不会修改到原来的代码。充分体现了设计模式的开闭原则,依赖倒转原则,合成复用原则。所以我在之前的篇章中就说到,设计模式的精髓是这几个原则,具体的模式是围绕这几个内功心法创造出来的招式。当你不明白心法的时候,多练点招式,也能感受到心法的奥妙。
最后,我们来总结下装饰器模式的作用。
好处:可以让我们对之前的类进行很好的扩展。比起继承类的方式,装饰器模式对功能的扩展是很动态的。可以添加撤销,因为你还可以添加判断条件。你还可以编写很多各种各样的装饰类,以各样的顺序和次数进行装饰。
不好的地方:装饰类多了,功能相似,出了问题的时候,排错花的时间就长了。