设计模式之装饰器模式、IO流中的装饰器

9 篇文章 0 订阅
2 篇文章 0 订阅

设计模式之装饰器模式、IO流中的装饰器

装饰器特点

装饰器的定义:

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变原来类。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

对功能的扩展也可以通过继承扩展所需要功能的类的方法,但是Java中的继承时单继承,如果想要扩展多个功能就需要不断继承,代码相当冗余。
在这里插入图片描述

  • Component:为统一接口,也是装饰类和被装饰类的基本类型

  • ConcreteComponent:为具体实现类,实现了Component接口,也是被装饰类,他本身是个具有一些功能的完整的类。

  • Decorator:是装饰类,实现了Component接口的同时还在内部维护了一个ConcreteComponent的实例,并可以通过构造函数初始化。

  • ConcreteDecorator:是具体的装饰产品类,每一种装饰产品都具有特定的装饰效果。可以通过构造器声明装饰哪种类型的ConcreteComponent。

    注意:装饰器类可以有很多的变化
    1、被装饰器的统一的接口,可以是一个接口,也可以是抽象父类
    2、装饰器类Decorator可以不需要

代码示例

首先创建一个统一的接口,接口中声明了一个方法

/**
 * 统一接口,也是装饰类和被装饰类的基本类型
 */
public interface Component {
    void method();
}

创建一个该接口的具体实现类

/**
 * 为具体实现类,也是被装饰类,他本身是一个具有功能的完整类
 */
public class ConcreteComponent implements Component {

     // 其余变量和方法
    
    @Override
    public void method() {
        System.out.println("原来的方法");
    }
}

创建一个实现接口的装饰类,这个类中实现的method方法是调用了类中的component.method()方法,为后来继承这个装饰类的装饰器类对component方法的使用和扩展做准备。

/**
 * 装饰类
 * 实现了Component接口
 */
public abstract class Decorator implements Component {

    // 内部维护一个ConcreteComponent实例
    protected Component component;

    // 通过构造函数实例化ConcreteComponent实例
    public Decorator(Component component) {
        super();
        this.component = component;
    }

    // Component接口提供的方法的实现是调用component的方法,自己没有实现
    @Override
    public void method() {
        component.method();
    }
}

定义两个装饰器类,装饰器类继承了装饰类,并且都有自己的自定义方法,而且对父类的方法进行了扩展。

/**
 * 具体装饰器类A
 * 继承自装饰器类
 */
public class ConcreteDecoratorA extends Decorator {

    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    public void methodA() {
        System.out.println("装饰器类A的扩展功能");
    }

    @Override
    public void method() {
        System.out.println("针对该方法进行一层A包装");
        super.method();
        System.out.println("包装结束");
    }
}
/**
 * 具体装饰器类B
 * 继承自装饰器类
 */
public class ConcreteDecoratorB extends Decorator {

    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    public void methodB() {
        System.out.println("装饰器类B的扩展功能");
    }

    @Override
    public void method() {
        System.out.println("针对该方法进行一层B包装");
        super.method();
        System.out.println("包装结束");
    }
}

所需要的类和接口都定义完成,下面我们写一个测试用例,来看一下装饰器这种设计模式是如何在不改变原有的类ConcreteComponent的情况下,给实例对象扩展多个所需要的功能的:

public class DecoratorTest {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();//原来的对象
        component.method();//原来的方法
        System.out.println("------------------------");
        ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA(component);//装饰成A
        concreteDecoratorA.method();
        concreteDecoratorA.methodA();//装饰成A以后新增的方法
        System.out.println("-------------------------");
        ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB(component);//装饰成B
        concreteDecoratorB.method();
        concreteDecoratorB.methodB();
        System.out.println("-------------------------");
        concreteDecoratorB = new ConcreteDecoratorB(concreteDecoratorA);//装饰成A以后再装饰成B
        concreteDecoratorB.method();
        concreteDecoratorB.methodB();//装饰成B以后新增的方法
        System.out.println("----------------------");
    }
}

可以看到,每次执行method方法后,不仅有原有的方法实现,还有扩展的部分,并且可以实现原先的类中没有的别的装饰类自定义的方法:
在这里插入图片描述

IO流中的使用

public class IODecorator {
    public static void main(String[] args) throws IOException, FileNotFoundException {
        final String filepath = "C:/Users/Chuuuki/Desktop/test.txt";
        /**
         * InputStream相当于统一接口,是装饰类和被装饰类的基本类型(Component)
         * FileInputStream相当于原始的待装饰的对象,为具体实现类,也是被装饰类,他本身是个具有一些功能的完整的类
         *
         */
        InputStream inputStream = new FileInputStream(filepath);
        System.out.println("FileInputStream不支持mark和reset" + inputStream.markSupported());
        System.out.println("-----------------------");
        /**
         * 下面展示一种装饰器的作用BufferedInputStream
         *
         * BufferedInputStream是一个具体的装饰器类
         * 其定义如下:
         * BufferedInputStream extends FilterInputStream
         *
         * FilterInputStream是装饰类,其继承自InputStream
         * 内部存在一个inputStream实例
         *
         * BufferedInputStream提供了特有的方法:
         */
        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
        System.out.println("bufferedInputStream支持mark和reset:" + bufferedInputStream.markSupported()); // 提供实现自自定义的方法
        bufferedInputStream.mark(0); // 标记一下
        char c = (char) bufferedInputStream.read();
        System.out.println("文件的第一个字符:" + c);
        bufferedInputStream.reset(); // 重置
        c = (char) bufferedInputStream.read(); // 再读
        System.out.println("重置以后再读一个字符,依然会是第一个字符:" + c);
        bufferedInputStream.reset();
    }
}
  • InputStream是一个抽象类,不能被实例化,所以可以将其看作统一接口。(Component)
  • FileInputStream相当于需要被扩展功能的原来的类,因为器本身是不支持markreset方法的。(ConcreteComponent)
  • BufferedInputStream是一个具体的装饰器类,他是支持markreset方法的,这两个方法相当于其自定义的方法。(ConcreteDecorator)
  • BufferedInputStream继承了FilterInputStream类,这个类

在这里插入图片描述
是继承了InputStream的,并且里面维护了一个InputStream实例,所以在这里

FilterInputStream是一个装饰类。(Decorator)
在这里插入图片描述
运行结果如图所示,文件中内容为”Hello“,FileInputStream实例也可以进行mark和reset操作了:
在这里插入图片描述
这样就实现了没有改变FileInputStream类,并且扩展了inputstream实例的功能的需求。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值