JAVA装饰器模式详解LZ到目前已经写了九个设计模式,回过去看看,貌似写的有点凌乱,LZ后面会尽量改进。
那么本章LZ和各位读友讨论一个与JAVA中IO有着不解情缘的设计模式,装饰器模式。
定义:装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
这一个解释,引自百度百科,我们注意其中的几点。
1,不改变原类文件。
2,不使用继承。
3,动态扩展。
上述三句话一语道出了装饰器模式的特点,下面LZ给出装饰器模式的类图,先上图再解释。
从图中可以看到,我们装饰的是一个接口...
LZ到目前已经写了九个设计模式,回过去看看,貌似写的有点凌乱,LZ后面会尽量改进。
那么本章LZ和各位读友讨论一个与JAVA中IO有着不解情缘的设计模式,装饰器模式。
定义:装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
这一个解释,引自百度百科,我们注意其中的几点。
1,不改变原类文件。
2,不使用继承。
3,动态扩展。
上述三句话一语道出了装饰器模式的特点,下面LZ给出装饰器模式的类图,先上图再解释。
从图中可以看到,我们装饰的是一个接口的任何实现类,而这些实现类也包括了装饰器本身,装饰器本身也可以再被装饰。
另外,这个类图只是装饰器模式的完整结构,但其实里面有很多可以变化的地方,LZ给出如下两条。
1,Component接口可以是接口也可以是抽象类,甚至是一个普通的父类(这个强烈不推荐,普通的类作为继承体系的超级父类不易于维护)。
2,装饰器的抽象父类Decorator并不是必须的。
那么我们将上述标准的装饰器模式,用我们熟悉的JAVA代码给诠释一下。首先是待装饰的接口Component。
packagecom.decorator;
publicinterfaceComponent{
voidmethod();
}
接下来便是我们的一个具体的接口实现类,也就是俗称的原始对象,或者说待装饰对象。
packagecom.decorator;
publicclassConcreteComponentimplementsComponent{
publicvoidmethod(){
System.out.println("原来的方法");
}
}
下面便是我们的抽象装饰器父类,它主要是为装饰器定义了我们需要装饰的目标是什么,并对Component进行了基础的装饰。
packagecom.decorator;
publicabstractclassDecoratorimplementsComponent{
protectedComponentcomponent;
publicDecorator(Componentcomponent){
super();
this.component=component;
}
publicvoidmethod(){
component.method();
}
}
再来便是我们具体的装饰器A和装饰器B。
packagecom.decorator;
publicclassConcreteDecoratorAextendsDecorator{
publicConcreteDecoratorA(Componentcomponent){
super(component);
}
publicvoidmethodA(){
System.out.println("被装饰器A扩展的功能");
}
publicvoidmethod(){
System.out.println("针对该方法加一层A包装");
super.method();
System.out.println("A包装结束");
}
}
packagecom.decorator;
publicclassConcreteDecoratorBextendsDecorator{
publicConcreteDecoratorB(Componentcomponent){
super(component);
}
publicvoidmethodB(){
System.out.println("被装饰器B扩展的功能");
}
publicvoidmethod(){
System.out.println("针对该方法加一层B包装");
super.method();
System.out.println("B包装结束");
}
}
下面给出我们的测试类。我们针对多种情况进行包装。
packagecom.decorator;
publicclassMain{
publicstaticvoidmain(String[]args){
Componentcomponent=newConcreteComponent();//原来的对象
System.out.println("------------------------------");
component.method();//原来的方法
ConcreteDecoratorAconcreteDecoratorA=newConcreteDecoratorA(component);//装饰成A
System.out.println("------------------------------");
concreteDecoratorA.method(缪买网 www.miumai.com);//原来的方法
concreteDecoratorA.methodA();//装饰成A以后新增的方法
ConcreteDecoratorBconcreteDecoratorB=newConcreteDecoratorB(component);//装饰成B
System.out.println("------------------------------");
concreteDecoratorB.method();//原来的方法
concreteDecoratorB.methodB();//装饰成B以后新增的方法
concreteDecoratorB=newConcreteDecoratorB(concreteDecoratorA);//装饰成A以后再装饰成B
System.out.println("------------------------------");
concreteDecoratorB.method();//原来的方法
concreteDecoratorB.methodB();//装饰成B以后新增的方法
}
}
下面看下我们运行的结果,到底是产生了什么效果。
从此可以看到,我们首先是使用的原始的类的方法,然后分别让A和B装饰完以后再调用,最后我们将两个装饰器一起使用,再调用该接口定义的方法。
上述当中,我们分别对待装饰类进行了原方法的装饰和新功能的增加,methodA和methodB就是新增加的功能,这些都是装饰器可以做的,当然两者并不一定兼有,但一般至少会有一种,否则也就失去了装饰的意义。
另外,文章开篇就说道了IO与装饰器的情缘,相信各位就算不太清楚,也都大致听说过JAVA的IO是装饰器模式实现的,所以LZ也不再废话,在给出一个标准的模板示例以后,直接拿出IO的示例,我们真枪实弹的来。
下面LZ直接给出IO包中的部分装饰过程,上面LZ加了详细的注释以及各个装饰器的功能演示,各位可以和上面标准的装饰器模式对比一下,LZ不得不感叹,IO与装饰器的孽缘。
packagecom.decorator;
importjava.io.BufferedinputStream;
importjava.io.BufferedReader;
importjava.io.DataInputStream;
importjava.io.FileInputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.InputStreamReader;
importjava.io.LineNumberReader;
importjava.io.PushbackInputStream;
importjava.io.PushbackReader;
publicclassIOTest{
/*test.txt内容:
*helloworld!
*/
publicstaticvoidmain(String[]args)throwsIOException,ClassNotFoundException{
//文件路径可自行更换
finalStringfilePath="E:/myeclipseproject/POITest/src/com/decorator/test.txt";
//inputStream相当于被装饰的接口或者抽象类,FileInputStream相当于原始的待装饰的对象,FileInputStream无法装饰InputStream
//另外FileInputStream是以只读方式打开了一个文件,并打开了一个文件的句柄存放在FileDescriptor对象的handle属性
//所以下面有关回退和重新标记等操作,都是在堆中建立缓冲区所造成的假象,并不是真正的文件流在回退或者重新标记
InputStreaminputStream=newFileInputStream(filePath);
finalintlen=inputStream.available();//记录一下流的长度
System.out.println("FileInputStream不支持mark和reset:"+inputStream.markSupported());
System.out.println("---------------------------------------------------------------------------------");
/*下面分别展示三种装饰器的作用BufferedInputStream,DataInputStream,PushbackInputStream,LZ下面做了三个装饰器的功能演示*/
//首先装饰成BufferedInputStream,它提供我们mark,reset的功能
BufferedInputStreambufferedInputStream=newBufferedInputStream(inputStream);//装饰成BufferedInputStream
System.out.println("BufferedInputStream支持mark和reset:"+bufferedInputStream.markSupported());
本文档为【JAVA装饰器模式详解】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。