装饰器模式:
动态地给一个对象添加一些额外的职责,装饰模式相比生成子类更为灵活。
Component:抽象构件
ConcreteComponent 具体构件,要被装饰的类
Decorator:装饰角色,具体装饰器的父类
ConcreteDecorator: 具体装饰器角色
示例:
对一个字符串打印前,进行两个处理:1、转大写,2、删除所有的 aa 字符串。这两步顺序要求不一样就会产生不一样的结果。
装饰角色要实现抽象构件,并且要有抽象构件作为一个属性。
jdk 中装饰器的使用:
1、FilterInputStream 类就是一个装饰器类。
写法:装饰器和要被装饰的类实现同样的接口,并且在装饰器中有一个接口的属性,用于接口实现的委派。在装饰器类中实现接口方法委派给接口的子类。
2、ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File(filePath)));
ObjectInputStream 也是个装饰器,把FileInputStream 装饰成了ObjectInputStream 对象,从而把FileInputStream 实现增强为了对对象的流写入。
动态地给一个对象添加一些额外的职责,装饰模式相比生成子类更为灵活。
Component:抽象构件
ConcreteComponent 具体构件,要被装饰的类
Decorator:装饰角色,具体装饰器的父类
ConcreteDecorator: 具体装饰器角色
示例:
对一个字符串打印前,进行两个处理:1、转大写,2、删除所有的 aa 字符串。这两步顺序要求不一样就会产生不一样的结果。
伪代码如下:
//定义一个打印的接口,及抽象构件 interface Component{ void print();//打印 } //定义一个抽象类,实现需要处理的步骤,具体的打印可以在子类中实现。 abstract Test implements Component{ public void upcase(){}//转大写实现 public void replace(){}//替换实现 }这样会发现每一个顺序都会对应一个子类的实现。如果再加上几种操作要求顺序不同,那么子类就会很多。这时候装饰器模式就很容易处理。
装饰器模式实现如下:
1、还是使用上面的抽象构件
/** * 抽象构件 */ public interface Component extends Serializable{ void print(String str); }
2、抽象构件要有一个实现类,即具体的构件
/** * 具体构件 * 要被装饰的类 */ public class ConcreteComponent implements Component{ @Override public void print(String str) { System.out.println(str); } }3、每一个操作就是一个装饰器(ConcreteDecorator),装饰器要有一个装饰角色(Decorator),
装饰角色要实现抽象构件,并且要有抽象构件作为一个属性。
/** * 装饰器父类 */ public abstract class Decorator implements Component{ private Component component; public Decorator(Component component){ this.component = component; } @Override public void print(String str) { component.print(str); } }4、实现两个 ConcreteDecorator,都是Decorator 子类
/** * 装饰器A */ public class DecoratorA extends Decorator{ public DecoratorA(Component component){ super(component); } @Override public void print(String str) { //转大写 str = str.toUpperCase(); super.print(str); } }
/** * 装饰器A */ public class DecoratorB extends Decorator{ public DecoratorB(Component component){ super(component); } @Override public void print(String str) { //删除aa str = str.replaceAll("aa",""); super.print(str); } }5、测试
public static void main(String[] args) { //构件 Component component = new ConcreteComponent(); //装饰器 component = new DecoratorB(component); //装饰器 component = new DecoratorA(component); component.print("aabcccazz"); }只要两装饰器顺序不同,那么结果就会不一样了。
jdk 中装饰器的使用:
1、FilterInputStream 类就是一个装饰器类。
写法:装饰器和要被装饰的类实现同样的接口,并且在装饰器中有一个接口的属性,用于接口实现的委派。在装饰器类中实现接口方法委派给接口的子类。
FilterInputStream 装修了InputStream 接口,那么所有的InputStream 的子类都可以通过这个装修器类来装饰,装饰后可以直接使用InputStream 接口方法调用。具体实现是InputStream 接口来实现的。
FilterInputStream 的每一个子类都是一个装饰器,对InputStream类的增强。
2、ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File(filePath)));
ObjectInputStream 也是个装饰器,把FileInputStream 装饰成了ObjectInputStream 对象,从而把FileInputStream 实现增强为了对对象的流写入。