设计模式 装饰模式(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++设计模式——装饰模式 前言 在实际开发时,你有没有碰到过这种问题:开发一个类,封装了一个对象的核心操作,而这些操作就是客户使用该类时都会去调用的操作:而有一些非核心的操作,可能会使用,也可能不会 ...
随机推荐
- Theos 工程make package时报错
错误: /Applications/Xcode.app/Contents/Developer/usr/bin/make package requires you to have a layout/ d ...
- udp接收
char receive_buffer[500] = {0}; std::vector<std::string> mysplit(std::string str,std::string p ...
- Zeppelin 用jdbc连接hive报错
日志: Could not establish connection to jdbc:hive2://192.168.0.51:10000: Required field 'serverProtoco ...
- MAC OS U 盘制作与安装方法
伴随着 iMac 5K Retina 和新的 Mac mini 等硬件的发布,苹果终于都推出了 OS X Yosemite 系统正式版了!相信很多人都已经用上.不过对于一些不想升级,而是打算「全新安装 ...
- Unity 发布到IOS,Android的各种坑
Unity 发布到IOS的注意事项1.开发环境MAC环境:Xcode环境 7.2.1Unity环境:Unity5.32.基本说明首先,我说一下,这是我在对Unity发布到IOS的实际使用中,总结出来的 ...
- request获取ip
public static String getIp(HttpServletRequest request) { String ip = request.getHeader("x-forwa ...
- html和html5学习
html和html5学习 chorme.safari中的input或textarea html超链接(a)详细讲解 html5新增及删除标签 html表格 图片加alt属性 input的type属性 ...
- C# 压缩打包文件下载
C# 压缩打包文件下载 public class MyNameTransfom : ICSharpCode.SharpZipLib.Core.INameTransform { #region INam ...
- seajs +gruntjs 合作开发
nodejs的出现 让服务器端能运行 js commonjs规范 规范服务器端开发按照什么写法去写 包括模块化开发 ( 不同点 请求在本地 js加载) AMD规范 浏览器端开发的规范 (不同点: 浏览 ...
- 原生JavaScript+CSS3实现移动端滑块效果
在做web页面时,无论PC端还是移动端,我们会遇到滑块这样的效果,可能我们往往会想着去网上找插件,其实这个效果非常的简单,插件代码的的代码往往过于臃肿,不如自己动手,自给自足.首先看一下效果图: 分析 ...