java设计模式之装饰器模式
2021-03-17 09:27
标签:ted 方法 index txt mil ora esc 文档 区分 装饰器模式也叫作包装器模式,指在不改变原有对象的基础上,动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活,属于结构性设计模式。 装饰器模式提供了比继承更有弹性的替代方案(扩展原有对象的功能)将功能附加到对象上,因此装饰器模式的核心是扩展功能,使用装饰器模式可以透明且动态地扩展类地功能。 由上图可以看到,装饰器模式主要包含以下4个角色: import javax.swing.*; public class Client { //抽象组件 //具体组件 static abstract class Decorator implements Component { /** public void operation() { //具体装饰器A //具体装饰器B java中的IO流主要分为字符流和字节流,这里我们以常用的字符流的读(Reader)为例来分析。首先我觉得要理解装饰器模式在IO中的使用,首先我们必须要 明白怎么去区分哪些是装饰类,哪些是被装饰类。我们看上面的例子,发现具体的装饰类ConcreteDecoratorA和ConcreteDecoratorB的构造函数的参数都是顶层接 口的实例对象。我们先通过JDK API文档查看Reader接口有哪些实现类,然后我们根据这个规则去判断哪些实现类是装饰类,哪些实现类是被装饰类。 我们先来查看BufferedReader的构造方法,发现传入的参数是顶层抽象的实例对象,所以可以判定BufferedReader是一个装饰类,并且它不是抽象的,所以这里直接忽略 了抽象装饰器,直接实现了具体的装饰器。当然Reader也有抽象的装饰器,比如FilterReader,感兴趣的同学可以自己去看API,但是它的具体的装饰器实现很少用,当然 如果需要自定义Reader装饰器,可以去继承这个抽象装饰器实现。 我们再来看InputStreamReader的构造方法,发现传入的参数不是顶层抽象的实例对象,所以可以判断InputStreamReader是一个被装饰的类。 这里只列举这两个常用的被装饰类和装饰的类,目的只是为了让大家理解装饰器模式在IO流中是怎么实现的,我们来看看具体的使用我们读取下面路径下的 名字为xiaoniu.txt文件里面的内容,然后打印出来,先来看不使用装饰类即用InputStreamReader的情况下怎么使用: 先不着急使用装饰类,我们发现使用的时候还要传入一个InputStream的实例对象,通过查看JDK文档,我们发现InputStreamReader还有一个子类FileReader, 看看FileReader怎么使用: FileReader也起到增强的作用,只不过是通过子类的方式实现的,只是这种方式符合开闭原则,如果需要添加功能必须要修改子类,还要在接口添加抽象方法。 我们通常会读取文件里面的内容的时候,需要一行一行的读取,如果只用被装饰类的方法是很难实现的,这个时候我们的装饰器BufferedReader就闪亮登场了。 从代理模式UML类图和通用代码实现来看,代理模式与装饰器模式几乎一模一样。从代码实现来看,代理模式确实与装饰器模式也是一样的,但是这两种设计模式 所面向的功能扩展面是不一样的。 装饰器模式强调自身的功能扩展,着重类功能的变化,比如添加方法。而代理模式强调对代理过程的控制,主要是对已有的方法进行功能增强,比如spring中通过 AOP实现客户端请求日志的记录。 java设计模式之装饰器模式 标签:ted 方法 index txt mil ora esc 文档 区分 原文地址:https://www.cnblogs.com/liu-yi/p/13975429.html装饰器模式的定义:
装饰器模式地应用场景:
装饰器模式的UML类图:
装饰器模式的通用写法:
package com.liuyi.designmode.structure.decorator;
public static void main(String[] args){
Component c1 = new ConcreteComponent (); //首先创建需要被装饰的原始对象(即要被装饰的对象)
Decorator decoratorA = new ConcreteDecoratorA(c1); //给对象透明的增加功能A并调用
decoratorA .operation();
Decorator decoratorB = new ConcreteDecoratorB(c1); //给对象透明的增加功能B并调用
decoratorB .operation();
Decorator decoratorBandA = new ConcreteDecoratorB(decoratorA);//装饰器也可以装饰具体的装饰对象,此时相当于给对象在增加A的功能基础上在添加功能B
decoratorBandA.operation();
}
static interface Component {
/**
* 示例方法
*/
public void operation();
}
static class ConcreteComponent implements Component {
public void operation() {
//相应的功能处理
System.out.println("处理业务逻辑");
}
}
/**
* 持有组件对象
*/
protected Component component;
* 构造方法,传入组件对象
* @param component 组件对象
*/
public Decorator(Component component) {
this.component = component;
}
//转发请求给组件对象,可以在转发前后执行一些附加动作
component.operation();
}
}
static class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
private void operationFirst(){ } //在调用父类的operation方法之前需要执行的操作
private void operationLast(){ } //在调用父类的operation方法之后需要执行的操作
public void operation() {
//调用父类的方法,可以在调用前后执行一些附加动作
operationFirst(); //添加的功能
super.operation(); //这里可以选择性的调用父类的方法,如果不调用则相当于完全改写了方法,实现了新的功能
operationLast(); //添加的功能
}
}
static class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
private void operationFirst(){ } //在调用父类的operation方法之前需要执行的操作
private void operationLast(){ } //在调用父类的operation方法之后需要执行的操作
public void operation() {
//调用父类的方法,可以在调用前后执行一些附加动作
operationFirst(); //添加的功能
super.operation(); //这里可以选择性的调用父类的方法,如果不调用则相当于完全改写了方法,实现了新的功能
operationLast(); //添加的功能
}
}
}
分析装饰器模式在IO流中的使用:
package com.liuyi.designmode.structure.decorator;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
/**
* @ClassName IoTest
* @description:
* @author:liuyi
* @Date:2020/11/14 23:01
*/
public class IOTest {
public 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();
}
}
package com.liuyi.designmode.structure.decorator;
import java.io.FileReader;
/**
* @ClassName IoTest
* @description:
* @author:liuyi
* @Date:2020/11/14 23:01
*/
public class IOTest {
public static void main(String[] args) throws Exception {
//读取当前项目下的xiaoniu.txt
FileReader fileReader = new FileReader("xiaoniu.txt");
//设置一次读取1024个字节
char[] chars = new char[1024];
int index;
while ((index=fileReader.read(chars))!=-1){
System.out.println(String.valueOf(chars));
}
fileReader.close();
}
}
package com.liuyi.designmode.structure.decorator;
import java.io.BufferedReader;
import java.io.FileReader;
/**
* @ClassName IoTest
* @description:
* @author:liuyi
* @Date:2020/11/14 23:01
*/
public class IOTest {
public static void main(String[] args) throws Exception {
//读取当前项目下的xiaoniu.txt
FileReader fileReader = new FileReader("xiaoniu.txt");
BufferedReader bufferedReader = new BufferedReader(fileReader);
//设置一次读取1024个字节
String readLine = bufferedReader.readLine();
System.out.println(readLine);
}
}
装饰器模式与代理模式的区别:
装饰器模式的优点:
装饰器模式的缺点: