(十)装饰模式(Decorator)
最后更新于:2022-04-01 15:48:25
装饰模式(Decorator)就是使用被装饰的一个子类的实例,在客户端将这个子类的实例委托给装饰类。装饰模式是结成关系的一个替代方案。
简单的装饰模式是原理图入下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-07-12_5784560950815.png)
装饰模式以对客服端透明的方式增添了对象的功能,其在与动态的给对象添加了责任,当然这里的继承便是静态的。
其中重要的地方时装饰对象和真是对象有相同的接口,这样客户端就可以和真是对象一样的交互方式和装饰对象交互,然后装饰对象把所有从客户端接收过来的请求全部转发给真是对象,然后在返还给客户端,这样装饰对象就可以再转发前或者以后添加一些附加功能而不影响对真是对象的操作,这样在不改变原有类的基础想,可以实现对于原有类的这种额外功能的实现,增强了程序的复用性。
同时装饰模式比继承好的地方就是,装饰模式可以动态的对已经存在的类进行任意的组合,实现想要的功能,而继承是静态的实现,不能改变原有类的实现,如果要添加更多的功能,只有添加更多的派生类来实现,这个简洁在下面的例子里对于最后一次打印输出就有很明显的效果,定义好了两个装饰类以后,不用再定义第三个就可以实现两个装饰类排列组合的效果。下面就简单的做了一个通过对于手机接电话的一个扩展,接听电话之前有一个彩铃,接受电话之后会回拨一段广告,这样就出来了下面的例子:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-07-12_5784560964774.png)
~~~
package com.designpattern.decorator;
public interface Phone {
public void recevieCall(String name);
}
~~~
~~~
package com.designpattern.decorator;
public class ChinaMobile implements Phone {
@Override
public void recevieCall(String name) {
System.out.println("step recevie " + name + " call");
}
}
~~~
~~~
package com.designpattern.decorator;
public abstract class Decorator implements Phone {
private Phone phone;
public Decorator(Phone phone) {
this.phone = phone;
}
@Override
public void recevieCall(String name) {
this.phone.recevieCall(name);
}
}
~~~
~~~
package com.designpattern.decorator;
public class RingBeforeChinaMobileDecorator extends Decorator {
public RingBeforeChinaMobileDecorator(Phone phone) {
super(phone);
}
@Override
public void recevieCall(String name) {
System.out.println("step ring before recevie " + name + "call");
super.recevieCall(name);
}
}
~~~
~~~
package com.designpattern.decorator;
public class AdAfterChinaMobileDecorator extends Decorator {
public AdAfterChinaMobileDecorator(Phone phone) {
super(phone);
}
@Override
public void recevieCall(String name) {
super.recevieCall(name);
System.out.println("step ad after recevie " + name + " call");
}
}
~~~
~~~
package com.designpattern.decorator;
public class Client {
public static void main(String[] args) {
Phone phone = new ChinaMobile();
Decorator decorator = new RingBeforeChinaMobileDecorator(phone);
decorator.recevieCall("andimuise");
System.out
.println("**************************");
decorator = new AdAfterChinaMobileDecorator(phone);
decorator.recevieCall("halberd");
System.out
.println("**************************");
decorator = new RingBeforeChinaMobileDecorator(
new AdAfterChinaMobileDecorator(phone));
decorator.recevieCall("teacher");
System.out
.println("**************************");
}
}
~~~
最终输出结果为,很明显在第三次输出的时候我想同时实现两种效果,就把另一个装饰类为为了其中一个装饰类的属性,因为无论是装饰类还是真实类他们是实现的共同的接口,这样就对实现提供了很好的效果
~~~
step ring before recevie andimuisecall
step recevie andimuise call
**************************
step recevie halberd call
step ad after recevie halberd call
**************************
step ring before recevie teachercall
step recevie teacher call
step ad after recevie teacher call
**************************
~~~