说明

代码复用最好用委托,不要使用继承。
继承是一种紧密耦合,任何父类的改动都会影响子类,不利于系统维护。

实现思想:
通过委托机制,复用系统中的各个组件,在运行时,将这些功能组件进行叠加。
主要做到性能模块分离(组件分离,功能单一)


实现步骤:
1.定义组件接口(装饰者接口)
2.定义装饰者
2.1 实现组件接口
2.2 定义装饰对象
2.3 添加构造函数,传入装饰对象
3.定义 具体的组件、具体的装饰者 实现
4.组装组件

JDK中使用的装饰者模型:

OutputStreamInputStream

源码实践

组件接口

  1. package xin.rtime.design.decorate;
  2. // 组件接口
  3. public interface Component {
  4. String operation();
  5. }

具体的组件

  1. package xin.rtime.design.decorate;
  2. // 具体组件
  3. public class ConcreteComponent implements Component {
  4. @Override
  5. public String operation() {
  6. return "operation";
  7. }
  8. }

具体的装饰者

  1. package xin.rtime.design.decorate;
  2. // 具体装饰者
  3. public class ConcreteDecorator extends Decorator {
  4. public ConcreteDecorator(Component component) {
  5. super(component);
  6. }
  7. @Override
  8. public String operation() {
  9. return "ConcreteDecorator " + component.operation();
  10. }
  11. }

装饰者

  1. package xin.rtime.design.decorate;
  2. // 装饰者
  3. public abstract class Decorator implements Component {
  4. Component component;
  5. public Decorator(Component component) {
  6. this.component = component;
  7. }
  8. }

验证

  1. package xin.rtime.design;
  2. import java.io.BufferedOutputStream;
  3. import java.io.DataOutputStream;
  4. import java.io.File;
  5. import java.io.FileNotFoundException;
  6. import java.io.FileOutputStream;
  7. import java.io.IOException;
  8. import xin.rtime.design.decorate.ConcreteComponent;
  9. import xin.rtime.design.decorate.ConcreteDecorator;
  10. import xin.rtime.design.decorate.demo.PacketBodyCreator;
  11. import xin.rtime.design.decorate.demo.PacketHTMLHeaderCreator;
  12. import xin.rtime.design.decorate.demo.PacketHTTPHeaderCreator;
  13. public class DecoratorTest {
  14. @SuppressWarnings("resource")
  15. public static void main(String[] args) {
  16. // 基础装饰者模型
  17. ConcreteDecorator decorator = new ConcreteDecorator(new ConcreteComponent());
  18. System.out.println(decorator.operation());
  19. // 流的示例
  20. try {
  21. // 增加缓冲功能的流 --- 14ms
  22. DataOutputStream dos = new DataOutputStream(
  23. new BufferedOutputStream(new FileOutputStream(new File(("D:\\a.txt")))));
  24. // 没有缓存功能的流 -- 331ms
  25. //DataOutputStream dos = new DataOutputStream(
  26. // new FileOutputStream(new File(("D:\\a.txt"))));
  27. long begin = System.currentTimeMillis();
  28. for(int i=0;i<100000;i++)
  29. dos.writeLong(i);
  30. System.out.println("spend:" + (System.currentTimeMillis()-begin));
  31. } catch (FileNotFoundException e) {
  32. e.printStackTrace();
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. }

装饰者模式 - 图1