java设计模式之装饰器模式
装饰器模式的定义:装饰器模式也叫作包装器模式,指在不改变原有对象的基础上,动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活,属于结构性设计模式。 装饰器模式提供了比继承更有弹性的替代方案(扩展原有对象的功能)将功能附加到对象上,因此装饰器模式的核心是扩展功能,使用装饰器模式可以透明且动态地扩展类地功能。 装饰器模式地应用场景:
装饰器模式的UML类图:
? ? ?由上图可以看到,装饰器模式主要包含以下4个角色:
装饰器模式的通用写法:package com.liuyi.designmode.structure.decorator; ?
分析装饰器模式在IO流中的使用:java中的IO流主要分为字符流和字节流,这里我们以常用的字符流的读(Reader)为例来分析。首先我觉得要理解装饰器模式在IO中的使用,首先我们必须要 明白怎么去区分哪些是装饰类,哪些是被装饰类。我们看上面的例子,发现具体的装饰类ConcreteDecoratorA和ConcreteDecoratorB的构造函数的参数都是顶层接 口的实例对象。我们先通过JDK API文档查看Reader接口有哪些实现类,然后我们根据这个规则去判断哪些实现类是装饰类,哪些实现类是被装饰类。 ? ?我们先来查看BufferedReader的构造方法,发现传入的参数是顶层抽象的实例对象,所以可以判定BufferedReader是一个装饰类,并且它不是抽象的,所以这里直接忽略 了抽象装饰器,直接实现了具体的装饰器。当然Reader也有抽象的装饰器,比如FilterReader,感兴趣的同学可以自己去看API,但是它的具体的装饰器实现很少用,当然 如果需要自定义Reader装饰器,可以去继承这个抽象装饰器实现。 我们再来看InputStreamReader的构造方法,发现传入的参数不是顶层抽象的实例对象,所以可以判断InputStreamReader是一个被装饰的类。 ?这里只列举这两个常用的被装饰类和装饰的类,目的只是为了让大家理解装饰器模式在IO流中是怎么运用的,来看看具体的使用,我们读取项目路径下的 名字为xiaoniu.txt文件里面的内容,然后打印出来,先来看不使用装饰类即用InputStreamReader的情况下怎么使用: package com.liuyi.designmode.structure.decorator; import java.io.FileInputStream; java.io.FileReader; java.io.InputStreamReader; /** * @ClassName IoTest * @description: * @author:liuyi * @Date:2020/11/14 23:01 */ public class IOTest { static void main(String[] args) throws Exception { //读取当前项目下的xiaoniu.txt FileInputStream fileInputStream = new FileInputStream("xiaoniu.txt"); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream); 设置一次读取1024个字节 char[] chars = new char[1024]; int index; while ((index=inputStreamReader.read(chars))!=-1){ System.out.println(String.valueOf(chars)); } fileInputStream.close(); inputStreamReader.close(); } } 先不着急使用装饰类,我们发现使用的时候还要传入一个InputStream的实例对象,通过查看JDK文档,我们发现InputStreamReader还有一个子类FileReader, 看看FileReader怎么使用: java.io.FileReader; 读取当前项目下的xiaoniu.txt FileReader fileReader = new FileReader("xiaoniu.txt"); while ((index=fileReader.read(chars))!=-1){ System.out.println(String.valueOf(chars)); } fileReader.close(); } } FileReader也起到增强的作用,只不过是通过子类的方式实现的,只是这种方式不符合开闭原则,如果需要添加功能必须要修改子类,还要在接口添加抽象方法。 我们通常会读取文件里面的内容的时候,需要一行一行的读取,如果只用被装饰类的方法是很难实现的,这个时候我们的装饰器BufferedReader就闪亮登场了。 java.io.BufferedReader; ); BufferedReader bufferedReader = BufferedReader(fileReader); 设置一次读取1024个字节 String readLine = bufferedReader.readLine(); System.out.println(readLine); } } 装饰器模式与代理模式的区别:从代理模式UML类图和通用代码实现来看,代理模式与装饰器模式几乎一模一样。从代码实现来看,代理模式确实与装饰器模式也是一样的,但是这两种设计模式 所面向的功能扩展面是不一样的。 装饰器模式强调自身的功能扩展,着重类功能的变化,比如添加方法。而代理模式强调对代理过程的控制,主要是对已有的方法进行功能增强,比如spring中通过 AOP实现客户端请求日志的记录。 装饰器模式的优点:
装饰器模式的缺点:
? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |