修饰器设计模式

--最近我给女朋友买了一款可以更换外壳的手机。现在的外壳是红色的,假如我想用这款手机的时候,会更换成银灰色的外壳。但是我不能随意更换天线或者话筒,因为这些功能模块在手机生产的时候就已经被固定了。


在维基百科中的介绍是如此:

修饰模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。

我们来解释一下这段话,有几个关键词“动态”和“对象”。

首先解释一下动态,Java多态的实现方式:重载和重写。

重载是就是动态绑定,或者说是运行时绑定,具体体现在只有运行的时候根据传的参数来决定运行的方法,而重写是编译时绑定,具体表现为一旦在子类中覆盖了父类的方法,编译后引用此方法时都只会指向子类的实现了。

而在修饰模式中也是通过一定编程的技巧来达到这个动态绑定的效果。

简单来说,修饰模式的设计核心是用一个修饰器类作为容器来包裹原来的类,一般将原来的类对象作为构造器参数传入。

这里想必大家也注意到了,是把类的对象作为参数传入,而不是类。这也是上面的关键词“对象”,修饰器修饰的是对象,而并非类。

至于为什么会引入修饰模式呢?稍微讨论一下,如果不使用修饰器模式的话:

那么假设A类是基类,你需要基于A类的基础上扩展十几种功能,而且这些功能的实现都要是不同的一个子类。你将可能出现需要实现一个功能就要实现一个新的子类,甚至当你需要有多重功能组合的时候,这些子类又将成倍增长,不仅仅是耦合度高,而且类的数量也会产生一种“类爆炸”的效应。

如果用修饰器的话,就相当于一把开枪声音很大的枪支,可以往上面套上消音器,这样它就扩展了消音的功能,而且摘下来之后又和原来的枪一样了。或者在工业上我们随处可以见到这样的东西,耳机、话筒(外置)。

其实对于写框架或者对Java特别熟悉的人,应该都知道Java IO也是遵循了修饰器的设计模式。

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import org.junit.Test; public class FileReader { @Test
public void test() {
java.io.FileReader fr;
BufferedReader br = null;
try {
String path = this.getClass().getResource("1.txt").getFile();
File f = new File(path);
fr = new java.io.FileReader(f);
br = new BufferedReader(fr);
String str = br.readLine();
System.out.println(str);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null)
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

可以看到上面这段代码 BufferedReader(修饰器容器)包裹了FileReader(原类)对象,扩展了缓存功能。

在Spring中有一个与BeanFactory接口一样使用很频繁的单词 FactoryBean,就是用到了修饰器模式和工厂模式来实现的。

也就是相对于BeanFactory这个IOC容器而言,FactoryBean是一个能产生或者修改对象产生bean的一个特殊bean。也就是根据不同的原料生成不同的产品。

关于FactoryBean等更理解之后再做讨论。

修饰器模式(day04)的更多相关文章

  1. python设计模式之修饰器模式

    python设计模式之修饰器模式 无论何时我们想对一个对象添加额外的功能,都有下面这些不同的可选方法. [ ] 如果合理,可以直接将功能添加到对象所属的类(例如,添加一个新的方法) [ ] 使用组合 ...

  2. My.Ioc 代码示例——谈一谈如何实现装饰器模式,兼谈如何扩展 My.Ioc

    装饰器模式体现了一种“组合优于继承”的思想.当我们要动态为对象增加新功能时,装饰器模式往往是我们的好帮手. 很多后期出现的 Ioc 容器都为装饰器模式提供了支持,比如说 Autofac.在 My.Io ...

  3. PHP设计模式之装饰器模式

    装饰器模式:如果已有对象的部分内容或功能性发生改变,但是不需要修改原始对象的结构或不使用继承,动态的扩展一个对象的功能,则应该使用装饰器模式.简单点说:就是我们不应该去修改已有的类,而是通过创建另外一 ...

  4. java设计模式之 装饰器模式

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

  5. java IO之 字符流 (字符流 = 字节流 + 编码表) 装饰器模式

    字符流 计算机并不区分二进制文件与文本文件.所有的文件都是以二进制形式来存储的,因此, 从本质上说,所有的文件都是二进制文件.所以字符流是建立在字节流之上的,它能够提供字符 层次的编码和解码.列如,在 ...

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

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

  7. javascript装饰器模式

    装饰器模式 什么是装饰器 原名decorator 被翻译为装饰器 可以理解为装饰 修饰 包装等意 现实中的作用 一间房子通过装饰可以变得更华丽,功能更多 类似一部手机可以单独使用 但是很多人都愿意家个 ...

  8. 设计模式学习心得<装饰器模式 Decorator>

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

  9. react中的hoc和修饰器@connect结合使用

    在学习react-redux的时候,看到了修饰器这个新的属性,这个是es7的提案属性,很方便.于是我用@connect代替了connect(使用的时候需要配置,这里不赘述),省去了很多不必要的代码,但 ...

随机推荐

  1. php文件格式数组

    一个文件格式对应的数组$mime_types = array('gif' => 'image/gif','jpg' => 'image/jpeg','jpeg' => 'image/ ...

  2. Redis VS Memcached 转载

    引子: 在大数据时代,总希望存在一个Key-value存储机制,像HashMap一样在内存中处理大量(千万数量级)的key-value对,以便提高数据查找.修改速度. 所以,我们会想到,Memcach ...

  3. 使用PHP对数据库输入进行恶意代码清除

    这是一个有用的PHP函数清理了所有的输入数据,并删除代码注入的几率. function sanitize_input_data($input_data) { $input_data = trim(ht ...

  4. [vim]插件ctrlp

    ctrlp 这个插件可以快速搜索你的文件或者缓冲区 这样很多时候都不必打开nerdtree了. 直接利用快捷键C-p打开搜索命令.

  5. code first 尝试

    建表: 1.先用EF连接数据库,配置connectionStrings <configSections> <!-- For more information on Entity Fr ...

  6. 关于split splice slice 的一些事

    学的知识很久不用总会忘记,更何况这三个的拼写都差不多,在这里特意写下自己的一些见解,以便以后可以更好地理解. slice  : 定义:接收一个或两个参数,它可以创建一个由当前数组中的一项或多项组成的新 ...

  7. Java基础语法学习(1)switch...case

    switch...case的标准语法 switch(待选择的变量) { case 值1:语句1; break; case 值2:语句2: break; ....... case 值n:语句n; bre ...

  8. Linux中open函数以及退出进程的函数

    open函数的flag详解1 读写权限:O_RDONLY O_WRONLY O_RDWR (1)linux中文件有读写权限,我们在open打开文件时也可以附带一定的权限说明 (譬如O_RDONLY就表 ...

  9. 关于打开Eclipse时出现eclipse failed to create the java virtual machine与locking is not possible in the direc

    原文转自:http://www.cnblogs.com/steararre/p/4037453.html 今天在机子上使用Eclipse时候打开发现这两个问题,通过查阅资料膜拜大神博客得知解决方法,特 ...

  10. qt tablewidget中单个和批量删除代码如下(部分)截图如下

    def coltable(self):#行删除    row=self.downwidget.currentRow()    select=self.downwidget.isItemSelected ...