利用IDEA的debug带你读懂 装饰模式
假如有这样一个需求:
设计一个电话类,有最基础的打电话的功能。第一个需求是打电话之前播放一段铃声,这时候我们就很自然想到再写一个铃声电话类继承电话类,重写继承自父类的方法。现在又有新需求,打完电话后,还要给出当前的通话时间,而且也要实现第一个需求怎么办?好的,我们还可以使用继承,写一个类继承前面刚实现的铃声电话类……
看起来,设计的难度不大,但是假如我们有更多的需求,那么是不是要继承前面的类。假如我们对其中的一个父类进行了修改,那么实现它的子类都会发生变化,可见,这种设计方式类之间的耦合性是十分高的,那么有没有一种设计模式可以解决这种问题呢?
我们常说设计来源于生活,程序的设计也一样。例如我们去餐厅点餐时,我们选了一种主菜,但是我们还是需要添加其它的配料,我们仔细观察,配料是有很多种的,但是各个配料之间也是相对独立的,我们可以选择加A,B……,配料;另一个人也可以选择B,C,D……配料。主菜和配料也是一同放在了食品这个主操作屏幕上的,那么这个日常生活上的例子有没有为我们的设计提供思路呢?
装饰模式
一个电话接口
public interface Phone {
void call();
}
实现电话接口的基本类
public class iphoneX implements Phone{
@Override
public void call() {
System.out.println("打电话");
}
}
一个实现了电话接口的装饰器
后面所有的装饰器都是继承这个类
public class phoneDecration implements Phone{
private Phone phone;
public phoneDecration(Phone phone) {
this.phone = phone;
}
@Override
public void call() {
phone.call();
}
}
可以播放铃声的装饰器
public class MusicPhoneDecration extends phoneDecration {
public MusicPhoneDecration(Phone phone) {
super(phone);
}
public void play(){
System.out.println("放音乐");
}
@Override
public void call() {
play();
super.call();
}
}
可以给出时间的装饰器
public class GiveTimeDecoration extends phoneDecration{
public GiveTimeDecoration(Phone phone) {
super(phone);
}
public void giveTime(){
System.out.println("当前时间XX");
}
@Override
public void call() {
super.call();
giveTime();
}
}
测试类
public class test {
public static void main(String[] args) {
Phone phone = new iphoneX();
phone = new MusicPhoneDecration(phone);
phone = new GiveTimeDecoration(phone);
phone.call();
}
}
debug启动
注意看上图变量的层次结构!!
注意看上图,我们在调用phone.call()时候,来到了super.call(),很自然是去调用phoneDecration的call(),注意看我圈起来的!此时要调用的是MusicPhoneDecration的call()方法
执行完MusicPhoneDecration的play()方法,再去调用MusicPhoneDecration的call方法里面的super.call()方法
这时候又来到了phoneDecration这个类,因为MusicPhoneDecration也是继承于这个类的,我们观察这一步的phone变量的类型为iPhoneX这个类
执行完iPhoneX的call时候,开始返回
执行完给出时间这个函数后,整个过程就结束了
结果
我们通过装饰模式完成了给定的需求,让一个电话实现了许多功能。而且各个类之间的耦合性大大降低。符合开闭原则,我们可以继续为电话增加新的功能,编写一个功能类继承phoneDecration类即可,我们修改现有的功能不会影响到其它类的现有功能。