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

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

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

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 send2
before send1
send
after send1
after 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中很明显可以窥见,所以装饰者模式在于设计灵活架构方面还是比较重要的,模式的学习不是一朝一夕,结合实际的经验,灵活运用才是真正的高手!


你可能感兴趣的:(java,装饰者模式)