装饰者模式:轻松记住IO类的关系与API
开门见山

目录

概述与模型
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的关系图,你就会发现其中的奥秘了。

装饰者模式:轻松记住IO类的关系与API的更多相关文章
- Java设计模式--装饰器模式到Java IO 流
装饰器模式 抽象构件角色:给出一个抽象接口,以规范准备接受附加责任的对象. 具体构件角色:定义准备接受附加责任的对象. 抽象装饰角色:持有一个构件对象的实例,并对应一个与抽象构件接口一致的接口. 具体 ...
- JavaSE(一) IO类层次关系和各种IO流的用法总结
今天把IO流的这一知点进行一下总结,因为在之前使用io流的时候,就只知道几个重点常用的IO类,比如FileInputStream,BufferedInputStream(缓冲流)等等,但是不知道它处于 ...
- 从装饰者模式的理解说JAVA的IO包
1. 装饰者模式的详解 装饰者模式动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性 的替代方案. 装饰者模式设计类之间的关系: 其 中Component是一个超类,ConcreteC ...
- java设计模式4.适配器模式、装饰器模式
适配器模式 把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够工作. 1. 类的适配器模式 目标角色:期望的接口,对于类的适配器模式,此角色不可以是具体类 ...
- Head First设计模式 装饰者模式
装饰器模式 典型的例子:JAVA IO. 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个 ...
- 设计模式(三):“花瓶+鲜花”中的装饰者模式(Decorator Pattern)
在前两篇博客中详细的介绍了"策略模式"和“观察者模式”,今天我们就通过花瓶与鲜花的例子来类比一下“装饰模式”(Decorator Pattern).在“装饰模式”中很好的提现了开放 ...
- Java设计模式12:装饰器模式
装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...
- JAVA设计模式初探之装饰者模式
定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活.设计初衷:通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种 ...
- Head First 设计模式 第3章 装饰者模式
第3章 装饰者模式 1.定义/说明 动态.透明的将职责附加到对象上(或从对象上撤销),而不影响其他对象.若要扩展功能,装饰者模式提供了比继承更富有弹性的替代方案. 2.介绍 首先让我们先来介绍一下场景 ...
随机推荐
- 宋牧春: Linux设备树文件结构与解析深度分析(1) 【转】
转自:https://mp.weixin.qq.com/s/OX-aXd5MYlE_YoZ3p32qWA 作者简介 宋牧春,linux内核爱好者,喜欢阅读各种开源代码(uboot.linux.ucos ...
- koa中间层 文件下载的请求转发
背景: 前端用a标签发起下载文档的get请求 node中间层接到get请求后将请求转发到java后端 java后端返回文档流传递给node中间层 好处: 后端的java业务逻辑层接口.数据库不向外部暴 ...
- [转载]FFmpeg完美入门[4] - FFmpeg应用实例
1 用FFserver从文件生成流媒体 一.安装ffmpeg 在ubuntu下,运行sudo apt-get ffmpeg 安装ffmpeg,在其他linux操作系统下,见ffmpeg的编译过程(编译 ...
- Java杂知识汇总(自己积累的)
[前提] 接下来,可能需要开始学习Java了,所以现在将前辈们传递给我的经验都记录下来,免得再次问他们. [积累] 1. 关于重启Tomcat服务器: 当在开发过程中, | 修改Java代码 -- 需 ...
- java基础6 面向对象的详解
本文知识点(目录): 1.1.万物皆对象 1.2.面向对象的概述 1.3.面向对象(java语言)与面向过程(C语言)对比 1.4.面向过程 1.5.对象 1.6.面向对 ...
- LeetCode679. 24 Game
You have 4 cards each containing a number from 1 to 9. You need to judge whether they could operated ...
- IEEEXtreme 10.0 - N-Palindromes
这是 meelo 原创的 IEEEXtreme极限编程大赛题解 Xtreme 10.0 - N-Palindromes 题目来源 第10届IEEE极限编程大赛 https://www.hackerra ...
- 【LOJ】 #2132. 「NOI2015」荷马史诗
题解 k叉哈夫曼树,但是没有了二叉那样的最后一定能合并成一个树根的优秀性质,我们就不断模拟操作看看到了哪一步能用的节点数< k,然后先拿这些节点数合并起来 然后就可以k个k个合并了,大小一样先拿 ...
- 易普优APS高级计划排程系统系列提纲:行业知识,业务建模,排程算法,计划可视化,平台框架,案例分享
专注于高级计划排程系统研发与实施10来年了,国内外各种APS软件基本都研究过,这里列个提纲主要从6个方面跟大家一起讨论分享,欢迎大家鼓掌或拍砖 易普优APS高级计划排程系统系列001:行业知识,APS ...
- controller中,Failed to Initialize. Reason: TimeOut虚拟用花初始化超时
1.调整 Run-timesetting->Internet Protocol->references->Advaanced->Options 将HTTP-request co ...