设计模式 装饰模式(Decorator)

@author ixenos

装饰模式是什么


1.装饰模式以对客户端透明的方式对象的功能,是继承关系的一个替代方案,但装饰模式可以在不创造更多子类的情况下,对对象的功能进行扩展。

2.装饰模式以对客户端透明的方式动态地给一个对象附上更多的责任。换言之,客户端并不会觉得对象在装饰前后有什么不同。

3.装饰模式把对客户端的调用委派到被装饰类,而功能的增强在装饰类进行,装饰模式的关键在于这种扩展是完全透明的。

  例如IO中的过滤流,具体就是BufferedInputStream的构造器接受一个节点流,而相关操作底层调用节点流的操作。

4.装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。  

5.本质上,利用了的接口的多态性

装饰模式的特点


1.装饰对象和真实对象具有相同的接口,这样客户端就可以以和真实对象相同的方式与装饰对象进行交互

2.装饰对象包含一个真实对象的引用

3.装饰对象接受来自客户端的请求,它把这些请求转发给真实对象

4.装饰对象可以在转发这些请求之前或之后增加一些附加功能

  这样就确保了在运行时不用修改给定对象的结构就可以增加对象的功能,在面向对象设计中通常使用继承对类的功能进行扩展

装饰模式的角色


抽象构件角色(Component):(如InputStream)给出一个抽象接口,作为共同接口,以规范接收附加责任的对象。

具体构件角色(Concrete Component):(如FileInputStream)定义一个将要被附加责任的类,真实角色。

装饰角色(Decorator):(如FilterInputStream)持有一个构件对象的引用,并定义一个与抽象构件接口一致的接口。

具体装饰角色(Concrete Decorator):(如BufferedInputStream)负责给构件对象附加责任。

抽象构件角色

 public interface Component{
public void doSomeThing();
}

具体构件角色

 public class ConcreteComponent implements Component{

     @Override
public void doSomeThing(){
System.out.println("功能A");
}
}

装饰角色

 /*
一、实现构件接口
二、内部持有构件变量,用以接受构件从而进行装饰
三、以此建立了一个装饰器,由装饰器子类来拓展功能
*/
public class Decorator implements Component{
private Component component; public Decorator(Component component){
this.component = component;
} /*借由真实构件来调用*/
@Override
public void doSomeThing(){
component.doSomeThing();
}
}

 具体装饰角色

 /*
通过继承包装着构件的装饰器,另外添加功能; 而这对客户端来说是透明的,因为客户端把请求提交给构件,
产出也是构件产出,装饰器顺道唤醒了其他操作,
而这些操作可以用以优化处理过程或者增加额外的功能,
比如BufferedInputStream、DataInputStream等 */ public class ConcreteDecorator1 extends Decorator{
public ConcreteDecorator1(Component component){
super(component);
} @Override
public void doSomeThing(){
super.doSomeThing();
//功能增加
this.doAnotherThing();
} private void doAnotherThing(){
System.out.println("功能B");
}
}

 另一个具体装饰角色

 1 public class ConcreteDecorator2 extends Decorator{
public ConcreteDecorator2(Component component){
super(component);
} @Override
public void doSomeThing(){
super.doSomeThing();
//功能增加
this.doAnotherThing();
} private void doAnotherThing(){
System.out.println("功能C");
}
}

客户端

 public Client{
public static void main(String[] args){
Component component = new ConcreteComponent();
Component component1 = new ConcreteDecorator1(component); component1.doSomeThing(); //又包装一层
Component component3 = new ConcreteDecorator2(conponent1); component2.doSoneThing(); /*或者直接用匿名对象直接多层包装,这是IO常用的做法*/
Component component3 = new ConcreteDecorator2(new ConcreteDecorator1(new ConcreteComponent())); component3.doSomeThing();
}
}

装饰模式对比继承


  • 装饰模式

    • 用来扩展特定对象的功能
    • 动态运行时分配职责
    • 不需要生成特定对象的子类,装饰对象相当于具有复用性的工具
  • 继承

    • 用来扩展一类对象的功能
    • 静态编译时分配职责
    • 需要生成大量对应功能的子类,不可复用

装饰模式之于流的嵌套


  流的嵌套从装饰模式的角度来说过滤流之间是无所谓顺序的,但考虑到具体应用,执行格式化输出的流在外层,缓冲流在中间是坠吼滴(缓冲流可以普通输出!)!

  装饰模式的要求是:具体装饰对象给具体构件对象附加功能(注意是对象),要求扩展对象功能的同时,对客户端透明,这就需要具体装饰角色转发调用请求给具体构件角色,而具体装饰角色在转发的过程中可以对其进行扩展。具体到流就是过滤流内部维护一个从构造器接受的节点流,而各基本方法可以添加缓冲,再在合适的时候释放流,而且更可增加一些额外的功能。

设计模式 装饰模式(Decorator)的更多相关文章

  1. 设计模式-装饰模式(Decorator Pattern)

    装饰模式(Decorator Pattern):动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活

  2. [工作中的设计模式]装饰模式decorator

    一.模式解析 装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰模式的要点主要是: 1.需要对已有对象扩展新的功能,又不希望改变原有对 ...

  3. 设计模式——装饰模式(Decorator Pattern)

    装饰模式:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活. UML图: 模型类: Component类: package com.cnblog.clarck; /** ...

  4. 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern)

    原文:乐在其中设计模式(C#) - 装饰模式(Decorator Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern) 作者:weba ...

  5. 设计模式系列之装饰模式(Decorator Pattern)——扩展系统功能

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  6. 深入浅出设计模式——装饰模式(Decorator Pattern)

    模式动机 一般有两种方式可以实现给一个类或对象增加行为: 继承机制,使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是静 ...

  7. 二十四种设计模式:装饰模式(Decorator Pattern)

    装饰模式(Decorator Pattern) 介绍动态地给一个对象添加一些额外的职责.就扩展功能而言,它比生成子类方式更为灵活.示例有一个Message实体类,某个对象对它的操作有Insert()和 ...

  8. 设计模式-09装饰模式(Decorator Pattern)

    1.模式动机 一般有两种方式可以实现给一个类或对象增加行为: 继承机制:使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是 ...

  9. 装饰模式decorator

    C++设计模式——装饰模式 前言 在实际开发时,你有没有碰到过这种问题:开发一个类,封装了一个对象的核心操作,而这些操作就是客户使用该类时都会去调用的操作:而有一些非核心的操作,可能会使用,也可能不会 ...

随机推荐

  1. openstack trove,使pylint忽略错误

    一.什么是pylint Pylint 是一个 Python 代码分析工具,它分析 Python 代码中的错误,查找不符合代码风格标准和有潜在问题的代码. Pylint 是一个 Python 工具,除了 ...

  2. GridView”的控件 必须放在具有 runat=server 的窗体标记内 “错误提示”

    在做导出数据到EXCEL程序中,出现了错误提示:类型“GridView”的控件“GridView1”必须放在具有 runat=server 的窗体标记 解决办法  重写 VerifyRendering ...

  3. 学习Sass(二)

    前面简单介绍了sass的安装,特点和使用方法等,这里记录下sass的基本语法. 1.变量 2.运算 3.嵌套 4.代码复用 5.高级语法 6.自定义函数 一.变量 变量以$开始,像css属性那样赋值, ...

  4. netty(5)高级篇-私有协议栈

    来源:<Netty权威指南>  作者:李林峰 一.私有协议介绍 由于现代软件的复杂性,一个大型软件系统往往会被人为地拆分称为多个模块,另外随着移动互联网的兴起,网站的规模越来越大,业务功能 ...

  5. 如何运用xp_cmdshell 执行多行cmd命令

    因为需要利用sql  脚本调用外部程序,所以尝试xp_cmdshell 命令,发现其默认只能执行一行命令,最后找到了下面方法: 将多行cmd 命令处理成bat文件,然后直接利用所在路径+文件来执行: ...

  6. Linked List - leetcode

    138. Copy List with Random Pointer //不从head走 前面加一个dummy node 从dummy走先连head 只需记录当前节点 //这样就不需要考虑是先new ...

  7. CodeForces 710B Optimal Point on a Line

    递推. 先对$a[i]$进行从小到大排序. 然后计算出每个点左边所有点到这个点的距离之和$L[i]$,以及右边每个点到这个点的距离之和$R[i]$. 这两个都可以递推得到. $L\left[ i \r ...

  8. 技能学习经验与C语言学习调查

    技能学习经验与C语言学习调查 前言 要说的话,这还是我第一次写博客.不论是为了作业也好,为了将来的学习工作也好,写博客都是必不可少的,也算是个自我提升的途径吧.不过第一次写博客,就用从来没听说过的ma ...

  9. POJ 3414 Pots(BFS)

    Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Description You are g ...

  10. JavaScript忍者秘籍——运行时代码求值

    1. 代码求值机制 JavaScript中,有很多不同的代码求值机制. ● eval()函数 ● 函数构造器 ● 定时器 ● <script>元素 - 用eval()方法进行求值 作为定义 ...