装饰模式
Java设计模式中有一种设计模式可以动态的给一个类添加附加功能,并对于客户端透明,如果可附加的功能有多个,还可以对附加功能随便组合。这种设计模式就是装饰模式(Decorator Pattern),装饰模式在Java 的I/O中也用到了。也许你会说,添加功能的话,也可以通过继承父类来实现,这个是在要实现扩展的功能不是很多时,生成的子类不多,但当有大量的功能扩展,为了支持每一种的扩展,就可能要生成大量的子类,而装饰模式则是动态的扩展功能,通过对功能扩展的组合达到所需的扩展类,可以再不影响其他对象的情况下,动态并透明的方式对单个对象添加额外的功能,所谓的装饰,就是可以添加修改,并不会影响原来的类。在类不能生产子类时,装饰模式也可以给该类动态的添加功能。
装饰模式的由以下的几种角色构成:
1、抽象构建角色(Component):可以使接口也可以是抽象类,该角色是具体构建角色和装饰角色要继承或实现的,具体构建角色跟装饰角色之所以要实现或继承同一抽象构建角色,是为了可以用抽象构建角色来声明具体构建角色跟装饰角色。
2、具体构建角色(ConcreteComponent):该角色实现或继承抽象构建角色。
3、装饰角色(Decorator):该角色中持有一个抽象构建角色。
4、具体装饰角色(ConcreteDecorator):该角色将实现为具体构建角色附加的功能。
下面是具体的例子
抽象构建角色
1 package decorator; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public interface Component { 8 public void doSomething(); 9 }
具体构建角色
1 package decorator; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class ConcreteComponent implements Component { 8 9 //实现doSomething() 10 public void doSomething() 11 { 12 System.out.println("doSomething from ConcreteComponent"); 13 } 14 15 }
装饰角色
1 package decorator; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class Decorator implements Component { 8 //持有构建角色的对象 9 private Component comp; 10 public Decorator(Component com) { 11 this.comp = com; 12 13 } 14 //该类并没有添加新的功能,添加的新功能将在具体装饰类中实现 15 @Override 16 public void doSomething() 17 { 18 comp.doSomething(); 19 } 20 }
具体装饰角色一
1 package decorator; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class ConcreteDecorator1 extends Decorator { 8 9 public ConcreteDecorator1(Component com) { 10 super(com); 11 } 12 public void doSomething() 13 { 14 super.doSomething(); 15 16 this.doAnotherthing(); 17 } 18 //添加了新的功能 19 public void doAnotherthing() 20 { 21 System.out.println("do anotherthing from concreteDecorator1"); 22 } 23 24 }
具体装饰角色二
1 package decorator; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class ConcreteDecorator2 extends Decorator { 8 public ConcreteDecorator2(Component com) 9 { 10 super(com); 11 12 } 13 14 public void doSomething() 15 { 16 super.doSomething(); 17 this.doAnotherthing(); 18 } 19 //添加的新功能 20 public void doAnotherthing() 21 { 22 System.out.println("do anotherthing from concreteDecorator2"); 23 } 24 25 }
客户端
1 package decorator; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class Client { 8 public static void main(String[] args) { 9 Component com = new ConcreteDecorator2(new ConcreteDecorator1(new ConcreteComponent())); 10 com.doSomething(); 11 } 12 }
结果:
从上面的例子可以清楚的看到具体构建角色跟装饰角色具有相同的接口,装饰角色中持有构建角色的引用,实现的扩展功能在具体装饰类中添加。
装饰模式在I/O中的应用:
抽象构建角色相当于字符流中的InputStream/OutputStream,字节流中的Reader/Writer,
具体构建角色相当于FileInputStream/FileOutputStream,
装饰角色对应于FilterInputStream/FilterOutputStream,
具体装饰角色就对应于BufferedInputStream/BufferedOutputStream,DataInputStream/DataOutputStream。