首页 > 代码库 > 修饰器模式(day04)

修饰器模式(day04)

修饰器设计模式

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


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

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

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

首先解释一下动态,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)