开门见山

目录

概述与模型

1、概述

  含义:动态地将责任附加到对象上。若要拓展功能,装饰者提供了比继承更有弹性的替代方案。

  初衷:需要动态为某一个类拓展。通常我们会使用继承,但是继承的话,会产生很多子类、乱而杂,不便于管理。

2、模型

  

应用场景描述

  场景描述:假设我们家刚砌好一座房子,墙面全是光头墙。那么,假设一个装修公司的软件的一个模块要应对光头墙,而且公司也还不确定他们能提供哪些墙,现在只能确认有刷白漆墙、印花纸墙。那怎么办呢?看我们上面的类图。Component就是原始组件墙(裸露墙)、ConcreateDecorator就是真实组件墙(泥土墙)、Decorator就是抽象装饰者(提供公共的接口)、ConcreteDecorator就是真实装饰者(业务需求墙:白漆墙、印花墙、菊花墙、...)。通过装饰者设计模式,我们大概知道了真实组件墙可以无限拓展、真实装饰者可以无限拓展。

  要点:装饰者与被装饰者要继承实现同一个接口。

代码演示

1、抽象组件

public abstract class Component {
public abstract void display();
}

2、真实组件

public class ConcreteComponent extends Component{
public void display() {
System.out.println("我是一块泥土墙!");
}
}

3、抽象装饰者

public class Decorator extends Component{
protected Component component;
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Decorator(Component component) {
</span><span style="color: #0000ff;">this</span>.component =<span style="color: #000000;"> component;
} </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Component getComponent() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> component;
} </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setComponent(Component component) {
</span><span style="color: #0000ff;">this</span>.component =<span style="color: #000000;"> component;
} </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> display() {
component.display();
}

}

4、真实装饰者

//装饰者A:泥土墙
public class ConcreteDecoratorA extends Decorator {
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> ConcreteDecoratorA(Component component) {
</span><span style="color: #0000ff;">super</span><span style="color: #000000;">(component);
} @Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> display() {
</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.component.display();
System.out.println(</span>"在泥土墙上加上水泥!"<span style="color: #000000;">);
}

}

//装饰者B:带墙纸的墙
public class ConcreteDecoratorB extends Decorator {
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> ConcreteDecoratorB(Component component) {
</span><span style="color: #0000ff;">super</span><span style="color: #000000;">(component);
} @Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> display() {
</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.component.display();
System.out.println(</span>"在墙皮上添加墙纸"<span style="color: #000000;">);
}

}

5、客户端

public class Client {
public static void main(String [] args){
//新建一面泥土墙:原始组件对象
Component wall=new ConcreteComponent();
    </span><span style="color: #008000;">//</span><span style="color: #008000;">装饰者A:为泥土墙添加白漆</span>
ConcreteDecoratorA cementWall=<span style="color: #0000ff;">new</span><span style="color: #000000;"> ConcreteDecoratorA(wall);
cementWall.display();
System.out.println(</span>"-----------分割线-------------"<span style="color: #000000;">);
</span><span style="color: #008000;">//</span><span style="color: #008000;">装饰B:为泥土墙添加墙纸</span>
ConcreteDecoratorB paperWall=<span style="color: #0000ff;">new</span><span style="color: #000000;"> ConcreteDecoratorB(wall);
paperWall.display();
System.out.println(</span>"-----------分割线-------------"<span style="color: #000000;">); </span><span style="color: #008000;">//</span><span style="color: #008000;">装饰者B:为水泥墙:添加白漆、添加墙纸 是不是看见IO的影子了。</span>
ConcreteDecoratorB mixedWall=<span style="color: #0000ff;">new</span> ConcreteDecoratorB(<span style="color: #0000ff;">new</span> ConcreteDecoratorA(<span style="color: #0000ff;">new</span><span style="color: #000000;"> ConcreteComponent()));
mixedWall.display(); </span><span style="color: #008000;">//</span><span style="color: #008000;">对比是不是发现很类似:在IO流里面有处理流(装饰者)、节点流(真实组件)
</span><span style="color: #008000;">//</span><span style="color: #008000;">DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream(new File(""))));</span>

}

}

6、测试结果

思考与回顾

  根据上面的描述,可能还是有点糊里糊涂,我们总结一下。

  装饰者模式是什么?为组件动态拓展。比如点一碗白面,我一会儿加辣椒、一会儿加醋、一会儿加白糖。那么可以随时应对这种无理要求,就是装饰者模式干的事情。

  便于拓展拓展拓展,应对变化变化变化。

  假设,我们上述例子,又要添加业务了,要计算一共花费的金额,那你有idea了吗?不妨动手开始做吧,无非就是添加一个方法、一次累加。例如装饰者B

 public int sale(){
return this.money+this.sale();
}

  其实,除了上述描述还隐藏一个设计模式:适配器模式 new FileInputStream(new File()),敬请期待我的适配器模式;

  大概就是这样,最后附上IO的关系图,你就会发现其中的奥秘了。

  

最新文章

  1. 运行WPS遇到的问题及解决办法
  2. 网络子系统55_ip协议分片重组_加入ipq
  3. Control character in cookie value, consider BASE64 encoding your value , java操作cookie遇到中文会报错的解决方案
  4. Codeforces Round #205 (Div. 2) : A
  5. 浅析Java中的反射机制原理
  6. 解析Infopath生成的XSN结构
  7. css ie6最小高度问题
  8. 深度神经网络(DNN)反向传播算法(BP)
  9. Mysql 启动遇到 The server quit without updating PID file (/[FAILED]l/mysql/data/021rjsh216086s.pid)和Attempted to open a previously opened tablespace
  10. [BZOJ1061] [Noi2008] 志愿者招募 (费用流)
  11. .net core 多租户框架整理
  12. 下拉列表模仿placeholder效果
  13. TX2-入门坑点-Ubuntu16.04任务栏消失
  14. OAuth 2.0 C# 版
  15. 分布式理论(一) —— CAP 定理
  16. HTML5 学习总结(三)——本地存储(localStorage、sessionStorage、WebSqlDataBase、IndexedDB)
  17. day 81 天 ORM 操作复习总结
  18. Android复习
  19. oracle客户端不需要配置tnsnames.ora文件直接连接服务器数据库
  20. Vulkan Tutorial 01 开发环境搭建之Windows

热门文章

  1. linux下生成core dump文件方法及设置【转】
  2. U3D模拟仿真实现
  3. HDU 1560 DNA sequence(IDA*)
  4. Sublime Text 2之Emmet插件安装及使用
  5. html学习-js
  6. Three.js基础探寻七——Lamber材质与Phong材质
  7. js监测设备类型【安卓,ios,苹果微信,电脑pc】
  8. python的select和epoll
  9. Qt Installer Framework实战
  10. python的进阶--爬虫小试