Java设计模式之装饰者模式
来源:互联网 发布:三枪内裤怎么样 知乎 编辑:程序博客网 时间:2024/05/21 05:21
装饰者模式,通过这种设计模式为一个对象动态的加上一系列的动作,而不需要因为这些动作的不同而产生大量的继承类。这个模式在JDK中几乎无处不在,例如:
java.io.BufferedInputStream
java.io.FileReader
…
这些类够熟悉吧,理解了装饰者模式就能更好地理解Java的IO体系,今天我们结合《Head First 设计模式》的例子来学习一下装饰者模式是怎么一回事。
装饰者模式的前世
先看看为什么需要这一模式。
原来我们要拓展新功能都是通过继承父类去产生新的子类。就拿书上的咖啡店举例子,饮料是基类,饮料各式各样,名称做法不一,就会拓展出一堆子类,随着客户需求增多,饮料的品种也会增多,如果我们一个新品种一个子类的话,回过头去看系统,我们会发现简直爆炸,有很多类需要我们去维护。一旦原料价格有变化或者饮料配方需要改进,我们就不得不去修改原有的类。这种做法违背了我们面向对象设计原则之一:类应该对扩展开放,对修改关闭。原有的代码可能经过多次测试确定功能无误,但你一旦修改了原来的代码,就不能保证原来的确定性了,所以我们应该尽可能拒绝这种做法。基于以上的分析,对于饮料,我们可以这样设计,最基本的饮料,然后配上(装饰)想要的配料,再委托计算出新饮料的价格(配料价格+原来的价格)。我们看看书上对装饰者模式的定义:
装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
类图如图所示:
我们可以看到ConcreteComponent和Decorator都用到继承,这样做的是要保证装饰者和被装饰者都要是同一类型,我们利用继承来保证类型匹配,而不是利用继承来获得行为。那行为从哪来?装饰者和组件组合在一起,就产生新的行为。利用组合还有一个好处就是运行时动态扩展。下来我们直接看用代码是怎么实现的。
装饰者模式的今生
借用书上的例子,自己敲一遍。
(1)饮料基类
package Decorator;/** * Created by gray on 2017/9/23. */public abstract class Beverage { String desc = "UnKnown Beverage"; public String getDesc() { return desc; } public abstract double cost();}
(2)调料基类
package Decorator;/** * Created by gray on 2017/9/23. */public abstract class CondimentDecorator extends Beverage{ public abstract String getDesc();}
(3)普通咖啡
package Decorator;/** * Created by gray on 2017/9/23. */public class Espresso extends Beverage { public Espresso(){ desc = "Espresso"; } @Override public double cost() { return 1.99; }}
(4)调料(牛奶和摩卡)
package Decorator;/** * Created by gray on 2017/9/24. */public class Milk extends CondimentDecorator { Beverage beverage; public Milk(Beverage beverage){ this.beverage = beverage; } @Override public String getDesc() { return beverage.getDesc() + ", Milk"; } @Override public double cost() { return 0.50 + beverage.cost(); }}
package Decorator;/** * Created by gray on 2017/9/23. */public class Mocha extends CondimentDecorator { Beverage beverage; public Mocha(Beverage beverage){ this.beverage = beverage; } @Override public String getDesc() { return beverage.getDesc() + ", Mocha"; } @Override public double cost() { return 0.20 + beverage.cost(); }}
(5) 最后是测试代码和测试结果
package Decorator;/** * Created by gray on 2017/9/24. */public class Test { public static void main(String args[]){ Beverage beverage = new Espresso(); System.out.println("no Condiment : "+ beverage.getDesc() + " | total : $" + beverage.cost()); Beverage beverage1 = new Mocha(new Espresso()); System.out.println("have Mocha : " + beverage1.getDesc() + " | total : $" + beverage1.cost()); Beverage beverage2 = new Milk(new Mocha(new Espresso())); System.out.println("have Milk,Mocha : " + beverage2.getDesc() + " | total : $" + beverage2.cost()); }}
总结:装饰者模式要说的东西不是很多,弄清楚装饰者模式再去看jdk中的I/O的相关类就显得简单了,里面绝大多数类都是装饰者。装饰者模式虽然比继承多了些灵活性,但同时也不可避免地出现许多小类,增加了API的复杂性,所有得看场景,当我们需要为某个现有的对象,动态的增加一个新的功能或职责时,可以考虑使用装饰者模式;还有就是如上面分析所说的,子类会爆炸性增长地时候就要考虑使用装饰者模式。
- java设计模式之装饰者模式
- Java设计模式之装饰者模式
- java设计模式之装饰者模式
- Java设计模式之装饰者模式
- Java设计模式之装饰者模式
- Java设计模式之装饰者模式
- java设计模式之装饰者模式
- Java设计模式之装饰者模式
- Java设计模式之装饰者模式
- java设计模式之装饰者模式
- java设计模式之------装饰者模式
- Java设计模式之装饰者模式
- java设计模式之装饰者模式
- Java 设计模式之 -- 装饰者模式
- java设计模式之装饰者模式
- Java设计模式之---装饰者模式
- java设计模式之装饰者模式
- java设计模式之装饰者模式
- 冒泡排序法相关解析
- Hibernate学习---第十二节:Hibernate之数据抓取策略&批量抓取
- Hibernate学习---第十三节:Hibernate之锁机制&乐观锁实现
- Hibernate学习---第十四节:hibernate过滤器和拦截器的实现
- Hibernate学习---第十五节:hibernate之session线程安全
- Java设计模式之装饰者模式
- 微服务、分布式、公有云、私有云
- Spring介绍
- 数据流图和数据流程图的区别
- 为啥看到大神级的程序员基本都是外国人的形象
- Win10操作系统下,Java环境变量的配置和Java入门小程序“hello,world”的编译
- Vue.js 计算属性
- MyBatis入门基础(一) 为什么要用Mybatis
- mybatis入门基础(二)----原始dao的开发和mapper代理开发