第四十五讲 I/O流——初次认识装饰设计模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yerenyuan_pku/article/details/84574918

装饰设计模式的由来

现在有以下需求:要实现自己的一套IO系统,实现文件的读取。没必要百分百的跟JDK的功能一模一样。
首先,MyWriter类专门用于写出数据,为什么会有这个类呢?因为数据类型有很多,比如文本MyTextWriter,媒体MyMediaWriter,等等。就会向上提取公共方法类即MyWriter,可以有如下继承关系:

MyWriter//专门用于写出数据的类
	|---MyTextWriter
	|---MyMediaWriter
	|---。。。。。。//扩展的继续继承添加

但是又考虑到效率问题,要使用缓冲来提高效率。对写方法复写,那么又有如下继承关系。

MyWriter//专门用于写出数据的类
	|---MyTextWriter
			|---MyBufferedTextWriter
	|---MyMediaWriter
			|---MyBufferedMediaWriter

上述的体系还是是可以的。但是,这个MyWriter以后可能还会因为新的音频文件而必须新增加,那么就又有如下的继承关系图。

MyWriter//专门用于写出数据的类
	|---MyTextWriter
			|---MyBufferedTextWriter
	|---MyMediaWriter
			|---MyBufferedMediaWriter
	|---MyAudioWriter
			|---MyBufferedAudioWriter
	|---。。。。。。//扩展的继续继承添加

问题也就随之而来了,如果再多一个子类,又得增加一个缓冲的实现子类。虽然这个体系是可以使用的,但是扩展性不好,体系非常臃肿复杂。那么就要对现有的体系进行优化。所有的缓冲子类使用的技术都是相同的,没必要都给定义一个子类。现在可以直接单独定义一个缓冲类,如下:

/**
 * 专门为别人提高效率而存在的,所以,此类在初始化的时候,把被提高效率的对象传进来。
 */
class MyBufferedWriter {
	MyBufferedWriter(MyTextWriter text) {
		
	}
	
	MyBufferedWriter(MyMediaWriter media) {
	
	}
}

你可以这样理解:以前是有一个数据类型的类,就弄一个这个类的子类,弄个缓冲区来提高效率,来一个弄一个;现在是定义一个缓冲区,大家公用一个缓冲区,需要提高谁的效率,把谁传进来,这样公共方法就可以得到复用,如上代码所示。
但是,上面的类的实现,扩展性很差。只要添加了新数据类型,那么就得新添构造函数,所以还得继续优化。找到所有构造函数的参数的共同类型,通过多态的形式,可以提高扩展性。

/**
 * 通过多态的形式可以提高扩展性。
 * 现在传入的参数就可以是MyTextWriter、MyMediaWriter、...
 * 后期再出现新的子类,也可以接受
 */
class MyBufferedWriter extends MyWriter {
	private MyWirter w;
	
	MyBufferedWriter(MyWirter w) {
		
	}
}

为什么要继承MyWriter类呢?新定义的类的作用,就是带着缓冲技术的Writer,里面定义的也是写出行为,只是功能更强的写出行为。对写行为进行了增强,那么也是可以向上提升,也有写的动作,那么也是写的一份子,实现写的接口继承MyWriter也是OK的。
最后,上述的继承体系,就变成了如下体系,新体系的名字就叫作装饰者模式

MyWriter//专门用于写出数据的类
	|---MyTextWriter
	|---MyMediaWriter
	|---MyAudioWriter
	|---MyBufferedWriter

装饰设计模式的概念

当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能,那么自定义的该类称为装饰类。装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。

装饰设计模式与继承之间的优劣

装饰设计模式比继承要灵活,避免了继承体系臃肿;而且降低了类于类之间的关系(继承体系的时候,缓冲类必须继承相应的类。现在就不需要啦,没有直接关系了)。
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能,所以装饰类和被装饰类通常都是属于同一个体系中的(可以理解为实现共同的接口,或继承一样父类)。结构上来说,由原来的继承结构,变成了现在的组合结构(我里面有你的结构)。

装饰设计模式的灵活之处

继承不要写的过多,不要以继承为主。产生子类过多,体系会显得非常臃肿。假设现在有个对象,是一年前写的,现在你新来到公司,觉得他这个类的功能不够用了。我自己写个类,把他的对象传进来,然后就可以进行加强了,当我写的功能有问题的时候,就可以把我的注释掉,然后继续使用原来的,模块功能还在,项目继续可以使用。

案例

有以下四个类:

Person//共同父类,实现多态用
	|---Man//被装饰对象类
	|---Woman//被装饰对象类
	|---NewPerson//装饰类
package cn.liayun.wrapper;

/**
 * 装饰设计模式:
 * 当想要对已有的对象进行功能增强时,
 * 可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。
 * 那么自定义的该类称为装饰类。
 * 
 * 装饰类通常会通过构造方法接收被装饰的对象,
 * 并基于被装饰的对象的功能,提供更强的功能。
 * @author liayun
 *
 */
public class PersonDemo {

	public static void main(String[] args) {	
//		Man m = new Man();
		Woman m = new Woman();
//		SubMan mm = new SubMan();//子类
		NewPerson mm = new NewPerson(m);
		mm.chifan();
	}

}

/*
Person//共同父类,实现多态用
	|---Man//被装饰对象类
	|---Woman//被装饰对象类
	|---NewPerson//装饰类
*/

/**
 * 公共父类(为实现多态)
 * @author liayun
 *
 */
class Person {
	void chifan() {
		System.out.println("吃饭");
	}
}

/**
 * 被装饰的类(被增强对象)
 * @author liayun
 *
 */
class Man extends Person {
	void chifan() {
		System.out.println("男人吃饭");
	}
}

/**
 * 被装饰的类(被增强对象)
 * @author liayun
 *
 */
class Woman extends Person {
	void chifan() {
		System.out.println("女人吃饭");
	}
}

/**
 * 装饰类(要去增强目标对象的类)
 * 装饰类通常会通过构造方法接收被装饰的对象,
 * 并基于被装饰的对象的功能,提供更强的功能。
 * @author liayun
 *
 */
class NewPerson extends Person {
	private Person p;
	NewPerson(Person p) {
		this.p = p;
	}
	void chifan() {
		System.out.println("开胃酒");
		p.chifan();
		System.out.println("甜点");
		System.out.println("来一根");
	}
}

猜你喜欢

转载自blog.csdn.net/yerenyuan_pku/article/details/84574918