装饰者模式-有层次地组织代码

来源:互联网 发布:af淘宝旗舰店 编辑:程序博客网 时间:2024/05/17 07:00

       代码组织的方式可以分为横向和纵向,横向指的是抽象与具体的关系(接口或抽象类与实际类的关系),这种方式能够让代码依赖于抽象的东西,更加灵活地扩展,体现了对于增加开放,对于修改关闭的程序设计原则。对于稍微复杂的功能模块,我们需要考虑的不仅仅是横向的组织方式,在纵向(深度)上也需要考虑如何来组织依赖关系,总体的原则是高层依赖低层。更具体来说,注入基于抽象的类的引用到高层类。这里我们通过控制功能拆分粒度来确保灵活性。

       装饰者模式是一种非常常见的在代码深度层次上组织代码的方式。(个人认为无所谓装饰者模式,这种做法很常见。),那么这种模式是如何演化的呢?

1.最基本的需求场景

 一个人发邮件的方法通常是这样的:

class Person{public void SendEmail(){System.out.println("send");}}
逻辑很简单,就是发送,我们可以这样来调用:

Person p = new Person();p.SendEmail();
2.扩展需求场景

在发送邮件之前我们需要校验一些内容(比如是否有非法内容),发送之后我们需要写一个日志记录用户的行为,我们可以用一个类继承Person,然后重写sendEmail方法。

class SuperPerson extends Person{public void SendEmail(){System.out.println("before send");super.SendEmail();System.out.println("after send");}}
我们在调用父类的sendEmail方法前,做一些事情,在调用后再做一些事情。

我们调用的时候就是这样:

Person p1 = new SuperPerson();p1.SendEmail();
父类引用指向子类的对象,灵活性更好一些,任何继承自Person的子类都可以被指向;

3.延伸的需求场景

我们用继承自Person的类来做具体的事情,在实际情况下,顶级的Person通常是一个抽象类(或者接口),更多的时候是起到一个定义规范的作用,而实际的功能在子类中,这时候我们使用Person类来做事情就不合理了,需要使用Person的子类,这时候,我们需要一个容器-IOC容器,于是我们很自然地想到,我们可以使用IOC机制来注入实现了Person的子类。

class SuperPerson2 extends Person{private Person person;public SuperPerson2(Person p){this.person = p;}public void SendEmail(){System.out.println("before send");person.SendEmail();System.out.println("after send");}}
我们可以这样来使用:

Person p = new SuperPerson();Person p2 = new SuperPerson2(p);p2.SendEmail();
输出结果:

before send2before send1sendafter send1after send2
这里我们可以看到,其实这里包装了三层,person,superPerson,SuperPerson2,一层一层的关系很明显,并且中间任何一层都可以替换,因为是依赖于抽象的Person,这样从各个方向上都实现了较好的灵活性。

在Java中,I/O模块就是基于装饰者模式来设计的:

public class IOTest {    public static void main(String[] args) throws IOException {        // 流式读取文件        DataInputStream dis = null;        try{            dis = new DataInputStream(                    new BufferedInputStream(                            new FileInputStream("test.txt")                    )            );            //读取文件内容            byte[] bs = new byte[dis.available()];            dis.read(bs);            String content = new String(bs);            System.out.println(content);        }finally{            dis.close();        }    }}
从这个Test中很明显可以窥见,所以装饰者模式在于设计灵活架构方面还是比较重要的,模式的学习不是一朝一夕,结合实际的经验,灵活运用才是真正的高手!


0 0