【设计模式】装饰模式

【概念】

装饰者模式:

动态地将责任附加到对象上,若要扩展对象,装饰者模式提供了比继承更弹性的替代方案

 要点:装饰者与被装饰者拥有共同的超类,继承的目的是继承类型,而不是行为

装饰者包含一个超类的对象,这样,可以在被装饰者行为前或者行为后加上新的行为,甚至取代原有的行为

装饰者会使程序中出现很多小类,增加使用难度

使用场景:对象由主体+许多可选的部件或者功能构成,使用继承或者接口会产生很多类,且很难扩展。

【原则】

1. 多用组合,少用继承。

利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。

2. 类应设计的对扩展开放,对修改关闭。

【实现图解】


模式的简化:

1. 如果只有一个Concrete Component类而没有抽象的Component接口时,可以让Decorator继承Concrete Component。


2. 如果只有一个Concrete Decorator类时,可以将Decorator和Concrete Decorator合并。



装饰模式实例与代码实现:

  手机超类:

[java]  view plain  copy
  1. <span style="font-size:14px;">//定义一个接口,规定实现它的类必须具有具有打电话的功能  
  2. public interface Phone {  
  3.     public abstract void call();  
  4. }</span>  
  具体的手机类:

[java]  view plain  copy
  1. <span style="font-size:14px;">public class PhoneImpl implements Phone {  
  2.   
  3.     @Override  
  4.     public void call() {  
  5.         System.out.println("用手机打电话");  
  6.     }  
  7.   
  8. }</span>  
抽象装饰类:

[java]  view plain  copy
  1. <span style="font-size:14px;">public abstract class PhoneDecorate implements Phone {  
  2.     //定义一个Phone类型变量用于接收具体的手机对象  
  3.     private Phone phone;  
  4.     //构造函数要传递Phone类型变量  
  5.     public PhoneDecorate(Phone phone) {  
  6.         //因为Phone是接口,所以传递过来的必然是实现此接口的手机类的对象  
  7.         //,然后用phone将传递过来的对象接收  
  8.         this.phone = phone;  
  9.     }  
  10.     @Override  
  11.     public void call() {  
  12.         this.phone.call();  
  13.     }  
  14. }</span>  
具体装饰类:彩铃装饰类:

[java]  view plain  copy
  1. <span style="font-size:14px;">public class ColorPhoneDecorate extends PhoneDecorate {  
  2.     //构造方法,需要传递具体的手机对象  
  3.     public ColorPhoneDecorate(Phone phone) {  
  4.         //调用父类的构造方法,将具体手机对象传递给父类构造  
  5.         super(phone);  
  6.     }  
  7.     //重写call方法,添加播放彩铃功能,也就是对手机进行彩铃装饰  
  8.     @Override  
  9.     public void call() {  
  10.         System.out.println("播放彩铃");  
  11.         super.call();  
  12.     }  
  13. }</span>  

具体装饰类:广告装饰类:

[java]  view plain  copy
  1. <span style="font-size:14px;">public class GuangGaoPhoneDecorate extends PhoneDecorate {  
  2.     //同彩铃装饰类为同一级,调用父类的构造方法  
  3.     public GuangGaoPhoneDecorate(Phone phone) {  
  4.         super(phone);  
  5.     }  
  6.     //重写call方法,进行播放广告装饰  
  7.     @Override  
  8.     public void call() {  
  9.         super.call();  
  10.         System.out.println("播放广告");  
  11.     }  
  12. }</span>  

测试类:
[java]  view plain  copy
  1. <span style="font-size:14px;">public class PhoneTest {  
  2.     public static void main(String[] args) {  
  3.         //利用多态,声明一个具体手机对象  
  4.         Phone p = new PhoneImpl();  
  5.         p.call();  
  6.         //给手机对象用彩铃修饰  
  7.         PhoneDecorate pd = new ColorPhoneDecorate(p);  
  8.         pd.call();  
  9.         //给手机用广告功能修饰  
  10.         pd = new GuangGaoPhoneDecorate(p);  
  11.         pd.call();  
  12.         //给手机用彩铃、广告功能双重修饰  
  13.         pd = new GuangGaoPhoneDecorate(new ColorPhoneDecorate(p));  
  14.         pd.call();  
  15.     }  
  16. }</span>  
 
可以看出,修饰模式总共有四部分组成,1)抽象被修饰类或接口;2)具体被修饰类;3)抽象修饰类;4)具体修饰类。

装饰者模式在JDK中的运用

Java当中的IO是运用了装饰者模式的最典型的例子。

下面是一个简单的例子,通过BufferedReader对象来装饰InputStreamReader对象

BufferedReader input = new BufferedReader(new InputStreamReader(System.in));

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值