设计模式 装饰模式(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++设计模式——装饰模式 前言 在实际开发时,你有没有碰到过这种问题:开发一个类,封装了一个对象的核心操作,而这些操作就是客户使用该类时都会去调用的操作:而有一些非核心的操作,可能会使用,也可能不会 ...
随机推荐
- 深入.NET平台和C#编程
第一章 深入.NET框架 1.Microsoft.NET框架概述: 1).NET介绍 2)为什么需要.NET框架 通过如下两个问题说明为什么需要.NET框架 01,C#程序可以再不同平台(PDA,P ...
- Spring 注解式Aop 入门
首先在spring配置文件中加上 xmlns:aop="http://www.springframework.org/schema/aop" http://www.springfr ...
- 啥数据类型set补充、深浅拷贝与函数
#s1 = {1,2,3,1} """ s2 = ([2,5,6]) print(s1) s1.add(5) #添加元素"5" print(s1) s ...
- Shell终端收听音乐--豆瓣FM命令行版
douban.fm Terminal-based douban.fm inspired by douban.fm.该版本版基于Python2.* 安装Python2.* pacman -S pytho ...
- jsp中使用java函数
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> ${fn ...
- YUM变量
有一个简单的python命令可以看到yum的 releaserver.arch.basearch的值 /usr/bin/python -c 'import yum, pprint; yb = yum. ...
- 【hihoCoder 1466】后缀自动机六·重复旋律9
http://hihocoder.com/problemset/problem/1466 建出A串和B串的两个后缀自动机 对后缀自动机的每个状态求出sg值. 求出B串的\(sum(x)\),表示B有多 ...
- jmeter命令行运行-单节点
jmeter有自己的GUI页面,但是当线程数很多或者现在有很多的测试场景都是基于linux下进行压测,这时我们可以使用jmeter的命令行方式来执行测试,该篇文章介绍jmeter单节点命令运行方式. ...
- SAP HANA 创建属性视图
[Step By Step]SAP HANA创建属性视图(Attribute View) Demo Instruction: 从一张用户信息表中组合出相信地址. 1. 在modeler窗口中,找到相应 ...
- VMMap(查看内存工具)
来源: http://www.cnblogs.com/georgepei/archive/2012/03/07/2383445.html http://www.cnblogs.com/georgepe ...