装饰器模式,其代码结构和桥接模式很相似,不过解决的问题不尽相同
本次,我们拿Java IO类库来举例说明装饰器模式的使用
Java中的IO类库非常庞大,如果对IO类进行分类,可以基本分为
而且根据这四个版本的分类,进行扩展出了很多的子类了
那么,实际使用中,并不是直接去创建子类,而是要按照如下的使用方式
InputStream in = new FileInputStream(“/user/test.txt”);
InputStream bin = new BufferInputStream(in);
为什么创建一个BufferInputStream需要创建一个FileInputStream对象呢?
为什么不是直接创建BufferInputStream对象呢?
如果基于继承的话,我们在FileInputStream上,设置一个子类,BufferedInputStream的话,也可以
像支持基本数据类型的DataInputStream类,也可以直接继承FileInputStream类就行
但是如果,我们需要一个既能支持缓存,Buffered,也能读取基本数据类型的话,难道要创建一个子类BufferedDataFileInputStream吗?
那么两两组合,会导致多少个组合子类的出现啊
于是出现了基于装饰器的设计方案
我们将继承关系改为组合关系来解决
这样就是利用了简单的组合来增强直接使用了父类的实现
当然,支持解决我们上面说的组合子类的问题
InputStream in = new FileInputStream(“/test/test.txt”)
InputStream bin = new BufferedInputStream(in)
DataInputStream din = new DataInputStream(bin);
din.readInt();
这样,其既支持缓存,又可以按照基本数据类型来进行读取
其和代理模式,有异曲同工之妙
在代理类中,通过生产代理类,来增强原有类的逻辑
在装饰器模式的子类中,也可以增强原始类的原有逻辑
// 代理模式的代码结构(下面的接口也可以替换成抽象类) public interface IA { void f(); } public class A impelements IA { public void f() { //… } } public class AProxy impements IA { private IA a; public AProxy(IA a) { this.a = a; }
public void f() { // 新添加的代理逻辑 a.f(); // 新添加的代理逻辑 } } // 装饰器模式的代码结构(下面的接口也可以替换成抽象类) public interface IA { void f(); } public class A impelements IA { public void f() { //… } } public class ADecorator impements IA { private IA a; public ADecorator(IA a) { this.a = a; }
public void f() { // 功能增强代码 a.f(); // 功能增强代码 } } |
而且,在实际使用BufferedInputStream等类,并没有去直接使用InputStream,而InputStream这个抽象类中有很多默认的实现
为什么呢
如果直接使用了InputStream的功能,那么就没法去委托了
也就是传入了BufferedInputStream的实现,也没有直接去使用这个实现类的缓存红利
而且装饰器类只需要实现增强的方法就可以了,其他方法继承父类的默认实现
那么本章就讲完了
装饰器模式为了解决继承关系过于复杂的问题,使用了组合来代替继承
为了给原始类增强功能,而且可以嵌套使用多个装饰器
装饰器模式,其代码结构和桥接模式很相似,不过解决的问题不尽相同
本次,我们拿Java IO类库来举例说明装饰器模式的使用
Java中的IO类库非常庞大,如果对IO类进行分类,可以基本分为
而且根据这四个版本的分类,进行扩展出了很多的子类了
那么,实际使用中,并不是直接去创建子类,而是要按照如下的使用方式
InputStream in = new FileInputStream(“/user/test.txt”);
InputStream bin = new BufferInputStream(in);
为什么创建一个BufferInputStream需要创建一个FileInputStream对象呢?
为什么不是直接创建BufferInputStream对象呢?
如果基于继承的话,我们在FileInputStream上,设置一个子类,BufferedInputStream的话,也可以
像支持基本数据类型的DataInputStream类,也可以直接继承FileInputStream类就行
但是如果,我们需要一个既能支持缓存,Buffered,也能读取基本数据类型的话,难道要创建一个子类BufferedDataFileInputStream吗?
那么两两组合,会导致多少个组合子类的出现啊
于是出现了基于装饰器的设计方案
我们将继承关系改为组合关系来解决
这样就是利用了简单的组合来增强直接使用了父类的实现
当然,支持解决我们上面说的组合子类的问题
InputStream in = new FileInputStream(“/test/test.txt”)
InputStream bin = new BufferedInputStream(in)
DataInputStream din = new DataInputStream(bin);
din.readInt();
这样,其既支持缓存,又可以按照基本数据类型来进行读取
其和代理模式,有异曲同工之妙
在代理类中,通过生产代理类,来增强原有类的逻辑
在装饰器模式的子类中,也可以增强原始类的原有逻辑
// 代理模式的代码结构(下面的接口也可以替换成抽象类) public interface IA { void f(); } public class A impelements IA { public void f() { //… } } public class AProxy impements IA { private IA a; public AProxy(IA a) { this.a = a; }
public void f() { // 新添加的代理逻辑 a.f(); // 新添加的代理逻辑 } } // 装饰器模式的代码结构(下面的接口也可以替换成抽象类) public interface IA { void f(); } public class A impelements IA { public void f() { //… } } public class ADecorator impements IA { private IA a; public ADecorator(IA a) { this.a = a; }
public void f() { // 功能增强代码 a.f(); // 功能增强代码 } } |
而且,在实际使用BufferedInputStream等类,并没有去直接使用InputStream,而InputStream这个抽象类中有很多默认的实现
为什么呢
如果直接使用了InputStream的功能,那么就没法去委托了
也就是传入了BufferedInputStream的实现,也没有直接去使用这个实现类的缓存红利
而且装饰器类只需要实现增强的方法就可以了,其他方法继承父类的默认实现
那么本章就讲完了
装饰器模式为了解决继承关系过于复杂的问题,使用了组合来代替继承
为了给原始类增强功能,而且可以嵌套使用多个装饰器