装饰器模式

抽象构件角色:给出一个抽象接口,以规范准备接受附加责任的对象。

具体构件角色:定义准备接受附加责任的对象。

抽象装饰角色:持有一个构件对象的实例,并对应一个与抽象构件接口一致的接口。

具体装饰角色:负责给具体构件加上额外的责任。

什么时候使用:

1. 需要扩展一个类的功能,或者给一个类增加附加责任。

2. 需要动态的给一个对象增加功能,这些功能可以再动态的撤销。

3. 需要增加由一些基本功能的排列组合而产生的的大量的功能,从而使继承关系变得不现实。

我以给汽车换颜色为例:

汽车厂生产汽车实例,4S店可以喷漆换颜色。

Car接口:

/**
* Created by 001977 on 2019-04-12 11:39.
* 抽象构件角色
*/
public interface Car { /**
* 出厂车身颜色
*/
void skin();
}

具体构件卡罗拉:

/**
* Created by 001977 on 2019-04-12 11:42.
* 具体构件:COROLLA卡罗拉(灰色)
*/
public class Corolla implements Car { @Override
public void skin() {
System.out.println("超级无敌灰色");
}
}

4S店抽象装饰器:

/**
* Created by 001977 on 2019-04-12 11:45.
* 抽象装饰角色(4S店)
*/
public abstract class FourS implements Car { private Car car; public FourS(Car car) {
this.car = car;
} @Override
public void skin() {
car.skin();
}
}

具体装饰器:喷枪红

/**
* Created by 001977 on 2019-04-12 11:49.
* 具体装饰角色(红色喷漆)
*/
public class RedSprayPaint extends FourS { public RedSprayPaint(Car car) {
super(car);
} @Override
public void skin() {
super.skin();
System.out.println("花2000块钱喷红色的漆");
}
}

具体装饰器:喷枪白

/**
* Created by 001977 on 2019-04-12 11:49.
* 具体装饰角色(白色喷漆)
*/
public class WhiteSprayPaint extends FourS { public WhiteSprayPaint(Car car) {
super(car);
} @Override
public void skin() {
super.skin();
System.out.println("花1000块钱喷白色的漆");
}
}

测试运行:

public class Main {
public static void main(String[] args) throws IOException {
System.out.println("====================出厂颜色====================");
Car corolla = new Corolla();
corolla.skin();
System.out.println("====================换颜色====================");
RedSprayPaint red = new RedSprayPaint(new WhiteSprayPaint(corolla));
red.skin();
}
}

IO中的体现(以InputStream为例)

抽象构件角色:由InputStream扮演,这个抽象类为各种子类型流处理器提供统一的接口。

具体构件角色:由FileInputStream、ObjectInputStream 、ByteArrayInputStream 等原始流处理器扮演,他们实现了InputStream的接口,可以被装饰器装饰。

抽象装饰角色:由FilterInputStream扮演,他也实现了InputStream的接口。

具体装饰角色:由DataInputStream 、BufferedInputStream等扮演。

..

由于IO库中需要很多性能的各种组合,如果用继承方法实现,那么每一种组合都需要一个类,这样会造成大量性能重复的类出现。如果使用装饰器模式,那么类的数目大大减少,性能的重复也减到最少。因此装饰器模式是IO中的基本模式。

以InputStream【抽象构件】为例:上图中的流可以分为两类:原始流处理器【具体构件】(FileInputStream及其左边的类)和链接流处理器【装饰器】(实现FilterInputStream的类【具体装饰器】)。

首先InputStream定义了一些规范:

接着比如FileInputStream去实现,实际上它都是去调用本地方法的,请看:

然后装饰器也去实现InputStream的方法,关键是持有InputStream对象的实例

最后具体的装饰器比如:

BufferedInputStream装饰了InputStream的内部工作方式,使得流的读入操作使用缓冲机制,不会对每一次流读入的操作都产生一次物理读盘动作,从而提高了程序的效率。它的内部有个buf字节数组用来缓存数据。

读取的时候调用fill方法,简单来说就是先尝试获取缓冲区,然后再操作输入流将数据读入缓冲区,这期间还有一些细节比如调整pos不再赘述。

还有DataInputStream提供了一些直接读取某种类型的数据的方法,省的我们读取完再去做转换。

比如:readBoolean

它的读入操作read方法就是直接调用原始流处理器的方法,并不复杂

最后附上一张画了一天的IO继承关系图:

如果图片看不清,鼠标右键---在新标签页下打开图片

Java设计模式--装饰器模式到Java IO 流的更多相关文章

  1. JAVA设计模式--装饰器模式

    装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...

  2. 从源码角度理解Java设计模式——装饰者模式

    一.饰器者模式介绍 装饰者模式定义:在不改变原有对象的基础上附加功能,相比生成子类更灵活. 适用场景:动态的给一个对象添加或者撤销功能. 优点:可以不改变原有对象的情况下动态扩展功能,可以使扩展的多个 ...

  3. Java设计模式——装饰者模式

    JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...

  4. 【设计模式】Java设计模式 - 装饰者模式

    Java设计模式 - 装饰者模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自 ...

  5. 装饰器模式-Decorator(Java实现)

    装饰器模式-Decorator(Java实现) 装饰器模式允许向一个现有的对象添加新的功能, 同时又不改变其结构. 其中 "现有对象"在本文中是StringDisplay类. 添加 ...

  6. 【设计模式】装饰器模式与Java Servlet、Spring Session在其中的使用

    简述 装饰器模式,可以通过装饰器类,通过依赖原实现的方式(不使用继承),达到扩展原实现的目的.UML图如下: ServletRequestWrapper于其中的使用 ServletRequestWra ...

  7. java之装饰器模式

    Decorator Pattern(装饰器模式),定义:Attach additional responsibilities to an object dynamically. Decorators  ...

  8. 设计模式-装饰器模式(Decrator Model)

    文 / vincentzh 原文连接:http://www.cnblogs.com/vincentzh/p/6057666.html 目录 1.概述 2.目的 3.结构组成 4.实现 5.总结 1.概 ...

  9. C#设计模式--装饰器模式

    0.C#设计模式-简单工厂模式 1.C#设计模式--工厂方法模式 2.C#设计模式--抽象工厂模式 3.C#设计模式--单例模式 4.C#设计模式--建造者模式 5.C#设计模式--原型模式 6.C# ...

随机推荐

  1. 自己实现的typeOf函数1

    自己实现的typeOf函数:返回传入参数的类型 主要用于解决,js自带的typeof返回结果不精确:Ext JS中typeOf对字符串对象.元素节点.文本节点.空白文本节点判断并不准确的问题 js代码 ...

  2. GZIP压缩与解压

    public class GZIP { /** * 字符串的压缩 * * @param str * 待压缩的字符串 * @return 返回压缩后的字符串 * @throws IOException ...

  3. Android深入理解Context(一)Context关联类和Application Context创建过程

    前言 Context也就是上下文对象,是Android较为常用的类,但是对于Context,很多人都停留在会用的阶段,这个系列会带大家从源码角度来分析Context,从而更加深入的理解它. 1.Con ...

  4. Testlink1.9.17使用方法( 第四章 测试需求管理 )

    第四章 测试需求管理 QQ交流群:585499566 需求规格说明书是我们开展测试的依据.首先,我们可以对项目(产品)的需求规格说明书进行分解和整理,将其拆分为多个需求,一个项目可以包含多个需求,一个 ...

  5. sql面试 查找每个班级的前5名学生(取分类数据的前几条数据)

    关键字PARTITION BY 自己看代码喽~ SELECT * FROM ( SELECT ROW_NUMBER() OVER (PARTITION BY ClassType ORDER BY Sc ...

  6. C# ToString()日期格式

    C# ToString()日期格式 ToString:2016/9/27 0:00:00ToString("yyyy/MM/dd"):2016/09/27ToString(&quo ...

  7. Kubernetes入门-集群安装

    Kubernetes是谷歌开源的容器集群编排平台,是一个完备的分布式系统支撑平台,为容器化应用提供部署运行.资源调度.服务发现和动态伸缩等一系列完整功能,具有强大的故障发现和自我修复机制.服务滚动升级 ...

  8. MySQL- 简单操作命令及教程

    MySQL数据库(;表示结束语句) 关系型数据库 注释用 // db_name表示库名: b_name表示表名 1.进入.退出 root用户只能在本机连接,不可外部链接 进入:mysql -uroot ...

  9. Redis的中并发问题的解决方案小结

    什么是Redis的并发竞争问题 Redis的并发竞争问题,主要是发生在并发写竞争.考虑到redis没有像db中的sql语句,update val = val + 10 where ...,无法使用这种 ...

  10. July 12th, 2018. Thursday, Week 28th.

    People love what other people are passionate about. 人总是会爱上别人倾注热情的事物. From La La Land. This quote has ...