设计模式的学习(三)—— 装饰者模式
来源:互联网 发布:无法安装java 编辑:程序博客网 时间:2024/06/01 09:41
这一篇博客的主要内容是装饰者模式,在我看来是一种较为容易理解的设计模式:
- 装饰者模式的主要应用场景
- HeadFirst Design Pattern 书中示例
- JDK中装饰者模式的应用实例
装饰者模式的主要应用场景
装饰者模式主要适用于需要将责任动态地附加到对象上的应用场景,也就是“装饰”的效果。同样是实现功能扩展的目的,装饰者模式提供了比继承更有弹性的方案。
HeadFirst Design Pattern书中示例
在书中,作者给出的示例是星巴克的不同种类的咖啡,如加牛奶的深焙咖啡、加摩卡的意式浓缩等。需要计算出每种咖啡的价格,那么需要怎么样进行开发呢。
不好的设计
最容易想到的设计是设计出各种各样的子类,让所有的类似于加牛奶的深焙咖啡、加摩卡的意式浓缩都继承自咖啡的基类,然后分别对每一个子类计算其价格。然而,这种设计的问题是随着“调料组合”的增加,这可能会生产出无穷多的子类,从而产生“类爆炸”的现象。
而且考虑到”change”这一软件设计中永恒不变的真理,我们采用上述的继承计算价格的方法可能会因为出现以下的情况,而必须要修改代码:
- 调料(摩卡、奶泡、豆浆等)价格的改变
- 出现了新的调料
- 顾客需要双倍摩卡的咖啡
- …
这些情况的出现都是需要修改原代码的,这就违反了软件设计中的开闭原则了。
采用装饰者模式的设计
//声明Baverage接口public abstract class Baverage{ public abstract double cost();}//此处采用继承,只是为了声明CondimentDecorator是Baverage,方便使用多态的性质public abstract class CondimentDecorater extends Baverage{}//声明两种咖啡类型public class Espresso extends Baverage{ public double cost(){ return 1.99; }}public class HouseBlend extends Baverage{ public double cost(){ return 0.89; }}//声明两个装饰类public class Mocha extends CondimentDecorater{ Baverage baverage; public Mocha(Baverage baverage){ this.baverage = baverage; } public double cost(){ return 0.20 + baverage.cost(); }}public class Whip extends CondimentDecorater{ Baverage baverage; public Whip(Baverage baverage){ this.baverage = baverage; } public double cost(){ return 0.15 + baverage.cost(); }}//测试代码public class StarbuzzCoffee{ public static void main(String args[]){ Baverage baverage = new Espresso(); baverage = new Mocha(baverage); baverage = new Mocha(baverage); baverage = new Whip(baverage); System.out.println("the cost of the final coffe is: " + baverage.cost());; }}
测试结果为:
对比继承而言,以上代码的可扩展性是很非常强的。
JDK中装饰者模式的应用实例
在JDK中,装饰者模式中应用最典型的地方是在I/O相关的api中。以输入流为例,InputStream是一个抽象类,类似于上例中的InputStream,而FileInputStream、AudioInputStream等为待装饰的基类, 装饰者类也是InputStream类的子类,但为了与基类作区别,装饰者类在实现过程中有一个抽象类FilterInputStream(此处的抽象指FilterInputStrem的read方法仅返回in.read(),不实现具体修饰。)。
了解到这些,我们可以写以下代码,以实现将输入字符都变成小写字符的功能。
//LowerCaseInutStream,以实现将所有的大写的输入字符变成小写字符的功能。import java.io.FilterInputStream;import java.io.InputStream;import java.io.IOException;public class LowerCaseInputStream extends FilterInputStream{ public LowerCaseInputStream(InputStream in){ super(in); } public int read() throws IOException{ int c = super.read(); return (c == -1? c:Character.toLowerCase((char)c)); }}//测试import java.io.InputStream;import java.io.FileInputStream;import java.io.BufferedInputStream;import java.io.IOException;public class InputTest{ public static void main(String args[]){ int c; try{ InputStream in = new LowerCaseInputStream( new BufferedInputStream( new FileInputStream("test.txt"))); while((c = in.read()) >= 0){ System.out.print((char)c); } in.close(); }catch(IOException e){ e.printStackTrace(); } }}
test.txt中的内容为:
This is Decorative Pattern.
输出结果为:
由此可见装饰者模式的应用原理和实现了。
- 设计模式的学习(三)—— 装饰者模式
- 设计模式—装饰模式(三)
- 设计模式学习(三)---------装饰模式
- 设计模式学习(三)之装饰者模式
- 设计模式学习笔记(三)- -装饰者模式
- 三、装饰模式——设计模式学习笔记
- 设计模式学习之三装饰者模式(Decorator)——解决星巴兹扩张快的问题
- Java设计模式学习—装饰者模式(Decorator)
- 设计模式(三)装饰者模式
- 设计模式(三):装饰者模式
- 设计模式(三)——装饰模式
- 设计思想学习—装饰者模式
- 设计模式学习笔记(三):装饰者模式
- 设计模式学习笔记(三)装饰模式(Decorator)
- 设计模式学习(四)——装饰者模式
- 设计模式学习002——装饰者模式
- 设计模式学习之——装饰者模式
- 从零开始学习设计模式——装饰者模式
- select下拉框(支持筛选、多选)
- android View的事件分发
- Android 国际化button以及tablayout字母自动变大写问题
- C# LINQ to XML
- Linux搭建ftp服务器
- 设计模式的学习(三)—— 装饰者模式
- Java实现二维码的生成与识别
- 整理Linux查看系统日志的一些常用命令
- error_reporting( )—规定不同的错误级别报告
- 404和500错误页的配置
- 简单Maven的Web项目之验证码(Kaptcha篇)
- InputStreamReader 和 OutputStreamWriter
- MyBatis分页插件PageHelper的使用
- mysql索引:b tree索引和hash索引的区别