装饰模式,顾名思义就是对原有的对象进行装饰,添加新的东西。装饰模式可以在不创造更多的子类的模式下,将对象的功能加以扩展。
讲到装饰模式不得不说,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 来装饰就形成了一个具有存储缓冲区的文件流读的功能了。
从上述 讲解的装饰模式可以看出来,这就是使用装饰模式实现功能的添加。让数据以流的形式输入输出,然后存放在缓存区内进行接下来的操作。
只要弄懂了装饰模式的意思,具体的实现可以根据需要实现功能的添加。
水平有限,不吝赐教。
版权声明:本文为博主原创文章,未经博主允许不得转载。