结合JDK源码看设计模式——装饰者模式
定义
在不改变原有对象的基础之上,将功能附加到对象上
适用场景
- 扩展一个类的功能
- 动态的给对象增加功能,当功能不需要的时候能够动态删除
详解
在看到定义的时候,可能很多人会想,这不就是继承吗?的确很像,不过是比继承更加有弹性的替代方案。就像原型模式和new之间的关系一样,有区别,但是区别又不是特别大。装饰者一个很重要的词就是动态,他可以灵活的选择要这个功能还是不要。在装饰者中要有四个角色:抽象的实体类,具体的实体类,抽象的装饰者,具体的装饰者。下面画一个大致的uml图
实体类创建之后,如果想扩展实体类那么一般的想法是继承,当然继承也是其中方法之一。上面由uml图就可以看出,在装饰者模式下,我们可以通过装饰类下的扩展功能实现对抽象实体类的包装。当我们需要扩展功能就多加一个扩展功能,不需要扩展功能就不用添加,是一个很动态的扩展方式。下面具体看代码解析。
抽象实体类
public abstract class abstractcake { protected abstract string getcake(); protected abstract int cost(); }
实体类
public class cake extends abstractcake{ @override protected string getcake() { return "蛋糕"; } @override protected int cost() { return 100; } }
抽象装饰类(可以抽象也可以不抽象)
public class abstractdecorator extends abstractcake { private abstractcake abstractcake; public abstractdecorator(abstractcake abstractcake) { this.abstractcake = abstractcake; } @override protected string getcake() { return this.abstractcake.getcake(); } @override protected int cost() { return this.abstractcake.cost(); } }
扩展功能1
public class fruitdecorator extends abstractdecorator { public fruitdecorator(abstractcake abstractcake) { super(abstractcake); } @override protected string getcake() { return super.getcake()+" 加一层水果"; } @override protected int cost() { return super.cost()+20; } }
扩展功能2
public class sugerdecorator extends abstractdecorator{ public sugerdecorator(abstractcake abstractcake) { super(abstractcake); } @override protected string getcake() { return super.getcake()+" 多加糖"; } @override protected int cost() { return super.cost()+10; } }
测试类
public class test { public static void main(string[] args) { abstractcake ac=new cake(); ac=new fruitdecorator(ac); ac=new sugerdecorator(ac); system.out.println(ac.getcake()); } }
结果
具体的内存图
可以很清楚的看见ac这个抽象类下面一层层包着实体类,解析的时候每一层的包装类的getcake()方法都会送回给抽象实体类,而我的getcake()方法实现的是字符串增加。后面如果我还需要一层水果,那么我就多装饰一次。如果用继承实现,那么我要两层水果,不要糖,那么我就还需要再定义一个实现两层水果的子类,而装饰者模式就只需要修改客户端的ac类实现就行。在jdk中装饰者模式用的最出名的莫过于io流了,以inputstream为例子。下面是uml图
这就是典型的装饰者。平常我们只需要fileinputstream来读取文件,当我们有一些特殊功能需要,如:bufferedinputstream(完成了缓存功能,使读取文件速度大大提升)和datainputstream(把byte转换成java基本数据类型)我们就可以装饰一下inputstream,即灵活又方便。这样使得我们对fileinputstream流的处理更能达到我们想要的预期。当你理解了装饰者模式,我推荐你看这篇博客。这样你就能很好的理解io流的操作。
总结
装饰者模式是一个比继承更加灵活的扩展方式,要记住装饰者模式必不可少的4个类:抽象的实体类,具体的实体类,抽象的装饰者,具体的装饰者。再结合上面推荐的博客,我相信你不但能理解装饰者,还能更加清晰的理解jdk中的io流
上一篇: 第一式 策略模式