1, 介绍
装饰器模式是一种结构型的设计模式. 使用该模式的目的是为了较为灵活的对类进行扩展, 而且不影响原来类的结构. 有同学说可以通过继承的方式进行实现啊, 没错, 继承的确可以实现, 但是继承的成本相对比较高, 而且如果涉及到扩展多个功能的话, 继承实现起来的成本较大.
装饰器模式的思想是, 对原来的类进行一层封装, 通过依赖实现扩展. 但是装饰器的依赖有两个比较重要的特点.
第一, 装饰器的抽象类, 依赖的是原来类的接口. 装饰器的实现类与原本的类之间, 不会存在耦合的现象, 两个类可以各自进行对应的变化. 这一点与桥接模式是相同的.
第二, 装饰器的抽象类会同时继承原来类的接口, 从而保证装饰器的实现类具有与原来的类一样的方法, 只是装饰器实现类的方法有新的扩展. 可以理解为对原有类的某种功能或者特性的加强. 这样产生的效果就是, 从使用者的角度来看, 会更加的便捷, 因为原来的类与装饰器类具有一样的方法, 真是其中实际的功能和作用进行了加强.
装饰器模式的使用场景, 抽象来说就是需要扩展类但是又不想引入子类, 或者也可以根据字面的含义, 能与装饰或者功能加强有关的场景. 比如说, 一张画, 是可以欣赏的, 但是没有办法挂到墙上. 那么我们可以找一个相框(装饰器实现类), 将画放到相框中, 之后就可以把这个带相框的画挂到墙上了. 再比如说, 我们买了一张床, 就可以在上边睡觉了. 但是我们希望睡的更加舒服, 所以需要在床上增加一个装饰, 比如垫上床垫, 加上枕头, 盖上床单. 装饰之后, 它依然有承载睡觉的属性.
2, 案例
2.1, 背景
就举一个上文提到的画与画框的例子. 为了提高节操, 哦不, 是情操, 本同学需要观赏 (接口) 一下工艺品. 谈到观赏, 我们可以观赏油画和水墨画(接口实现类). 但是油画和水墨画无法挂在墙上让众人欣赏, 所以我们希望找一个相框(装饰器抽象类), 将画放进去, 然后挂起供人欣赏(装饰或者功能加强). 之后, 我们终于找到了一个木质的相框(装饰器实现类), 装饰之后, 具有更好的观赏效果.
2.2, 实现
1)定义观赏的接口
- public interface Look {
- public String LookAtPic();
- }
2)定义观赏的实现类
- public class InkPic implements Look
- { @Override
- public String LookAtPic()
- {
- return "欣赏水墨画";
- } }
- public class OilPic implements Look
- { @Override
- public String LookAtPic() {
- return "欣赏油画";
- } }
3)定义装饰器抽象类
- public abstract class PicDecorator implements Look
- {
- private Look look;
- public Look getLook() {
- return look;
- }
- public void setLook(Look look) {
- this.look = look;
- }
- public PicDecorator(Look look) {
- this.look = look;
- } @Override
- public abstract String LookAtPic();
- }
4)装饰器实现类
- public class WoodPicDecorator extends PicDecorator
- {
- public WoodPicDecorator(Look look) {
- super(look);
- } @Override
- public String LookAtPic() {
- return this.getLook().LookAtPic() + ", 木质相框";
- } }
5)运行
- public class Test {
- public static void main(String[] args)
- {
- OilPic oilPic = new OilPic();
- System.out.println(oilPic.LookAtPic());
- WoodPicDecorator woodPicDecorator = new WoodPicDecorator(oilPic);
- System.out.println(woodPicDecorator.LookAtPic());
- InkPic inkPic = new InkPic();
- System.out.println(inkPic.LookAtPic());
- woodPicDecorator = new WoodPicDecorator(inkPic);
- System.out.println(woodPicDecorator.LookAtPic());
- } }
5)结果
欣赏油画
欣赏油画, 木质相框
欣赏水墨画
欣赏水墨画, 木质相框
Process finished with exit code 0
3, 总结
装饰器模式的关键代码有两点: 第一, 装饰器抽象类依赖原接口; 第二, 装饰器抽象类实现原接口.
优点: 低成本扩展类的方法(功能加强)
缺点: 这种方法非常精巧, 非要找一个缺点的话, 那就是精巧的东西一般都不太好理解.
Java 设计模式(9)---------- 装饰器模式
来源: http://www.bubuko.com/infodetail-2565660.html