设计模式 装饰模式(Decorator)
设计模式 装饰模式(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)的更多相关文章
- 设计模式-装饰模式(Decorator Pattern)
装饰模式(Decorator Pattern):动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活
- [工作中的设计模式]装饰模式decorator
一.模式解析 装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰模式的要点主要是: 1.需要对已有对象扩展新的功能,又不希望改变原有对 ...
- 设计模式——装饰模式(Decorator Pattern)
装饰模式:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活. UML图: 模型类: Component类: package com.cnblog.clarck; /** ...
- 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern)
原文:乐在其中设计模式(C#) - 装饰模式(Decorator Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern) 作者:weba ...
- 设计模式系列之装饰模式(Decorator Pattern)——扩展系统功能
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- 深入浅出设计模式——装饰模式(Decorator Pattern)
模式动机 一般有两种方式可以实现给一个类或对象增加行为: 继承机制,使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是静 ...
- 二十四种设计模式:装饰模式(Decorator Pattern)
装饰模式(Decorator Pattern) 介绍动态地给一个对象添加一些额外的职责.就扩展功能而言,它比生成子类方式更为灵活.示例有一个Message实体类,某个对象对它的操作有Insert()和 ...
- 设计模式-09装饰模式(Decorator Pattern)
1.模式动机 一般有两种方式可以实现给一个类或对象增加行为: 继承机制:使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是 ...
- 装饰模式decorator
C++设计模式——装饰模式 前言 在实际开发时,你有没有碰到过这种问题:开发一个类,封装了一个对象的核心操作,而这些操作就是客户使用该类时都会去调用的操作:而有一些非核心的操作,可能会使用,也可能不会 ...
随机推荐
- FZU 2089 数字游戏
Problem 2089 数字游戏 Problem Description 现在,给你2个整形数字A和B.你的任务就是计算出A+B的结果C后,统计C中数字5出现的次数. Input 输入数据第一行 ...
- 取汉子拼音首字母的C#和VB.Net方法
转载http://blog.fwhyy.com/2012/03/take-the-first-initials-method-of-csharp-and-vbnet/
- wifi 模块
#include"STC12C5A.H" #include <string.h> #include<intrins.h> #define uint unsi ...
- 图片添加border 不占用图片的大小
因为设计稿中的分割线大多分为两种情况:1.在图片右侧:2.在图片右侧+下方. 那么使用伪类before和after以及绝对定位很容易在不改变原布局的情况使图片按照设计稿输出和保留分割线. 例div.i ...
- openstack私有云布署实践【19 通过python客户端 创建实例VM指定IP地址】
还有一种创建方式 是使用py开发工具,调用openstackclient的方法进行创建实例 ,好处就是可随意指定我们要的虚拟机IP地址,需求的场景就是,某天我们需要主动分配一个比较熟知的IP用作某个服 ...
- PhpSrom安装xdebug
1.php需要安装xdebug,这样能支持调试. 下载地址:http://www.xdebug.org/download.php,若不清楚下载版本,可将phpinfo的信息复制到下载地址页面的cust ...
- Number Sequence (HDU 1711)
Number Sequence Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- JqGrid的总结大全【转】
jqGrid整理 PS:JqGrid 官方 API 点我 我的笔记: 一. jqGrid的加载. 1.引用相关头文件 引入CSS: <link href="Scripts/jq ...
- Base64encode
一直以来Base64的加密解密都是使用sun.misc包下的BASE64Encoder及BASE64Decoder的sun.misc.BASE64Encoder/BASE64Decoder类.这个类是 ...
- [河南省ACM省赛-第三届] 网络的可靠性 (nyoj 170)
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=170 根据题意,需要找到度数为1的结点个数,如下图: #include<iostre ...