设计模式之(五)——装饰模式

装饰模式,顾名思义就是对原有的对象进行装饰,添加新的东西。装饰模式可以在不创造更多的子类的模式下,将对象的功能加以扩展。
讲到装饰模式不得不说,java 的 io 就是有利用装饰模式设计。
写两句代码就清楚了。
1、socket编程,读控制台输入的字符,我们会写:

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

2、文件读(写):

 BufferedReader br = new BufferedReader(new FileReader(file));

这里就使用了装饰模式,这其实就是将 InputStreamReader 对象和 FileReader 用BufferedReader 来进行装饰,然后就会得到了一个具有了缓存buff 功能的流读取方式了。

这里我们稍微总结一下。
装饰模式需要几个材料才能实现:
1、 抽象构建角色(Component):无论是抽象类还是接口,这里是 待装饰对象 和添加的 装饰对象 都需要有一个统一的接口实现(或继承)这样才能真正的实现装饰。(java io中如 InputStream/OutputStream 和Reader/Writer类)。

2、 具体的构建角色(ConcreteComponent):实现具体的待装饰的对象。我们都需要一个统一的“空白”对象,我们之后是给这个“空白”对象进行装饰,添加功能。(java io中如 FileOutputStream 和 FileInputStream)。

3、装饰角色(Docorator):统一的装饰对象。这里可以认为是定义需要添加的装饰的一个抽象。这里可以根据 装饰的样式不同 定义不同的子类,在进行添加时互不干扰。(装饰的多变可以有)。

4、具体的装饰角色(ConcreteDecorator):真正意义上的装饰,即添加的功能对象。(java io中如 BufferedOutputStream 和 BufferedInputStream,DataOutputStream 和 DataInputSrtream)。

这里我们来解释下,如图:
这里写图片描述

这里 有一个 待装饰ConcreteComponent 只有装饰 Docorator 后才能形成一个整体 Component
然而可能我们需要装饰的功能不止一个,这是我们需要将功能 抽象成一个装饰类,然后添加功能时可以根据需要进行添加 装饰A 或者 装饰B 或者两者都加(两者都加和上一层的装饰类似)。

举个例子:

interface Component {
    public void doSth();
}

class ConcreteComponent implements Component {
    @Override
    public void doSth() {
        System.out.println("功能X");
    }
}

class Decorator implements Component {
    private Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void doSth() {
        component.doSth();
    }
}

class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    @Override
    public void doSth() {
        super.doSth();
        System.out.println("功能A");
    }
}

class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    @Override
    public void doSth() {
        super.doSth();
        System.out.println("功能B");
    }
}

public class Test {
    public static void main(String[] args) {
        Component component = new ConcreteDecoratorA(
                              new ConcreteDecoratorB(
                              new ConcreteComponent()));
        component.doSth();
    }
}

运行结果就是在实现自身功能的同时实现了添加的功能。如图:
这里写图片描述
这里就是先将 B 的的功能装饰上去,然后将 A 的功能装饰上去,这样就形成了新的类,同时实现 X,B,A 的功能。

不过这里的装饰类是比较通常的实现方法,这里也有简洁的实现方式,正如我上面说的那样,比如 :
1、直接在 带装饰类 中添加功能时,就不需要接口(抽象类)Component 。只需添加的装饰是带装饰类的子类即可。
2、装饰添加的只有一个对象功能时我们可以不需要 装饰类的抽象层 Decorator

那么现在,我们再回头再看看java 的 io。

public abstract class Reader 

public class BufferedReader extends Reader

public class InputStreamReader extends Reader 

public class FileReader extends InputStreamReader

BufferedReader br = new BufferedReader(new FileReader(file));

我们可以看到 上述 BufferedReader ,InputStreamReader ,FileReader 的祖先都是 Reader。
然后 FileReader 用 BufferedReader 来装饰就形成了一个具有存储缓冲区的文件流读的功能了。

从上述 讲解的装饰模式可以看出来,这就是使用装饰模式实现功能的添加。让数据以流的形式输入输出,然后存放在缓存区内进行接下来的操作。

只要弄懂了装饰模式的意思,具体的实现可以根据需要实现功能的添加。

水平有限,不吝赐教。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值