装饰者模式-《Head First 设计模式》第三章
来源:互联网 发布:你曾是少年 知乎 编辑:程序博客网 时间:2024/06/06 09:23
源自《Head First 设计模式》,只进行个人总结方便复习,初次学习者不会有任何收获,请看原著!
1-定义:
动态的将责任附加到对象身上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
2-设计原则:
类应该对扩展开放,对修改关闭。
装饰者包装一个组件,等于,装饰者具有组件(component)的一个引用。
1、 实现过程中使用了继承,不是说利用装饰而避免继承的吗?
装饰者(Decorator)继承自组件(Component),这里实际意义是“装饰”,原因在于,通过继承只是为了“类型匹配”而不是为了继承获得某些行为。
2、如何获得行为?
在“装饰”的过程中,添加新的行为,而不是继承自超类,这就是组合对象。
3、通常装饰者模式采用抽象类实现,而java中可以用接口实现。
实例:星巴克
星巴克需要出售各种饮料,并且在饮料上加上调料,比如+奶泡+豆浆的浓缩咖啡,比如+摩卡和豆浆的烘焙咖啡。需要实现Beverage饮料类(抽象组件)、Condiment调料类(抽象装饰者)、具体饮料类(继承Beverage)、具体调料类(Condiment)。
Beverage
public abstract class Beverage { String description = "unKnow description"; public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public abstract double cost();}
Condiment
public abstract class Condiment extends Beverage{ public abstract String getDescription();}
Espresso\DarkRoast\HouseBlend(浓缩咖啡\烘焙咖啡)
public class Espresso extends Beverage{ public Espresso(){ description = "Espresso "; } public double cost() { return 8; }}
其余类推
Whip\Soy\Mocha(奶泡\豆浆\摩卡)
public class Mocha extends Condiment{ Beverage beverage; public Mocha(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ", Mocha "; } public double cost() { return beverage.cost() + 1; }}
其余类推
测试
Beverage beverage = new Espresso(); System.out.println(beverage.getDescription()+beverage.cost()); beverage = new HouseBlend(); beverage = new Soy(beverage); beverage = new Whip(beverage); beverage = new Mocha(beverage); System.out.println(beverage.getDescription()+beverage.cost()); beverage = new DarkRoast(); beverage = new Whip(beverage); beverage = new Soy(beverage); System.out.println(beverage.getDescription()+beverage.cost());
实现方法总结:
- 定义一个抽象组件Component—为所有类的超类
- 定义抽象装饰者Decorator,继承自抽象组件C
- 实现各种具体组件,都继承自抽象组件C
- 实现各种具体装饰者,都继承自抽象装饰者D
- 使用代码:
Component c = new ChildComponent(); //某个具体组件c = new DecoratorOne(c); //进行一层装饰c = new DecoratorTwo(c); //进行第二层装饰c = new DecoratorThree(c); //进行第三层装饰c.doSomeThing(); //用最终装饰好的组件去做一些操作
装饰者应用:JAVA I/O
Java I/O中FileInputStream
>BufferedInputStream
>LineNumberInputStream
就是层层被包装。
- FileInputStream(被装饰组件,提供最基本的字节读取功能)
- BufferedInputStream(装饰者:增加利用缓冲输入增强性能和用readline()方法来增强接口两种行为)
- LineNumberInputStream(装饰者:加上计算行数的能力)就是层层被包装。
java I/O中的组件和装饰者:
抽象组件:InputStream
具体组件(被装饰者):FileInputStream、StringBufferInputStream、ByteArrayInputStream
- 装饰者(抽象类):FilterInputStream
- 具体装饰者:BufferedInputStream、DataInputSream等等
缺点:
设计中包含大量的小类,导致使用该API程序员的困扰。
实现自己的Java I/O
我们制作一个InputStream用于将得到的字符串中的大写字母都转换为小写模式。主要实现方法就是,继承FilterInputStream然后重写read()
和read(byte b[], int offset, int len)
方法。
LowerCaseInputStream
public class LowerCaseInputStream extends FilterInputStream{ protected LowerCaseInputStream(InputStream arg0) { super(arg0); }//for byte public int read() throws IOException{ int c = super.read(); return ((c == -1)? c : Character.toLowerCase((char)c)); }//for byte array public int read(byte b[], int offset, int len) throws IOException{ int result = super.read(b, offset, len); for(int i = offset; i < offset + result; i++) { b[i] = (byte)(Character.toLowerCase((char)b[i])); } return result; }}
测试程序
需要写好一个txt文件,我放在E盘
int c; try { //nested Decorators InputStream inputStream = new LowerCaseInputStream( new BufferedInputStream( new FileInputStream("E:\\test.txt"))); while((c = inputStream.read()) >= 0) { System.out.print((char)c); } } catch (IOException e) { e.printStackTrace(); }
Java中还有很多部分也是使用了装饰者模式,本质就是不断嵌套装饰添加行为的过程,还是比较简单的。但是会导致出现大量的子类。
- 装饰者模式-《Head First 设计模式》第三章
- [设计模式]head first 设计模式之PHP实现 第三章 装饰者模式
- Head First设计模式-装饰者模式
- 《Head First 设计模式》装饰者模式
- Head First 设计模式--装饰者模式
- Head First-设计模式:装饰者模式
- Head First设计模式C++实现--第三章:装饰者(Decorator)模式
- 《Head first 设计模式》之装饰模式
- Head First装饰者模式
- Head First: 装饰者模式
- Head First---装饰者模式
- Head First 装饰者模式
- Head First设计模式:(三)装饰者模式
- Head First Java 设计模式——装饰者模式
- Head First 设计模式(3)- 装饰者模式 笔记
- Head First设计模式之观察者,装饰者模式
- 《Head First 设计模式》之装饰者模式
- 《Head First 设计模式》读书笔记之装饰者模式
- CSS居中布局
- 洛谷3938 斐波那契
- 使用Osmocom软件以及UmTRX ,教你如何制作一个GSM基站
- Uva 10820
- 往Qtquick项目中添加images文件夹
- 装饰者模式-《Head First 设计模式》第三章
- 深入源码理解YYCache 、SDWebImage、AFNetworking、NSCache 缓存方式与对比
- oracle数据库查询语句in后面的参数个数超过1000的处理方式
- xml 用法解析
- Go语言奇妙点
- 中国国测局地理坐标(GCJ-02)、世界标准地理坐标(WGS-84) 、百度地理坐标(BD-09)坐标系转换
- JavaScript的循环以及数据类型
- Javascript with用法
- 使用VS(C#) 对Mysql 进行操作