装饰器模式
装饰器模式就是动态地给一个对象添加一些额外的职责,扩展对象的功能.对于增加功能来说,装饰器模式比生成子类更为灵活.
装饰器模式的结构
通常来说,给一个对象添加一些额外的功能,可以通过继承来实现,但是这并不能动态地给对象添加职责,如果要添加一些职责,只能改变原有对象. 这时候就需要有装饰器模式出现了. 装饰器模式并不是利用继承和多态来扩展和复用功能,是基于对象组合的方式 .
装饰器模式的角色有:
- 抽象的对象角色 给出一个抽象接口,以规范准备接受附加功能的对象
 - 具体的被装饰者 一个将要接受附加功能的具体实现,就是被装饰者,需要实现抽象的对象接口
 - 装饰抽象类 持有一个被装饰者的实例,并实现抽象对象接口,为具体的装饰功能提供一个统一的接口
 - 具体装饰角色 就是具体的装饰对象,继承子装饰抽象类,是用来给被装饰者添加附加功能的.
 
看类图:

装饰对象和被装饰对象实现的都是同一个接口,装饰对象也可以是一个接口,下面还可以有更多的具体的装饰对象.通过调用一个方法来装饰被装饰对象,以此来添加新的功能附件.
实例
比如我们现在要实现一个给人动态添加服装的功能.
首先定义一个接口,就是被装饰者实现的接口 里面有一个方法就是为人动态添加衣服1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public abstract class Person {
    private String name ;
    private String sex;
    protected String getSex() {
        return sex;
    }
    protected void setSex(String sex) {
        this.sex = sex;
    }
    protected String getName() {
        return name;
    }
    protected void setName(String name) {
        this.name = name;
    }
    public abstract  void show();
}
接着实现具体要穿衣服的人1
2
3
4
5
6
7
8
9
10
11
12public class Man extends Person {
    public Man(String name, String sex) {
        super.setName(name);
        super.setSex(sex);
    }
    
    public void show() {
        System.out.println("装扮"+getName()+getSex());
    }
}
在实现装饰抽象类 定义一个统一的装饰接口1
2
3
4
5
6
7
8
9
10
11
12
13
14public abstract class Decorator extends Person {
    protected Person person;
    public void decorator(Person person){
        this.person = person;
    }
    
    public void show() {
        if(person != null){
            person.show();
        }
    }
}
具体装饰实现类1
2
3
4
5
6
7
8
9
10
11
12
13
14public class TShirts extends Decorator {
    
    public void show() {
        System.out.println("穿T恤");
        super.show();
    }
}
public class Shorts extends Decorator  {
    
    public void show() {
        System.out.println("穿短裤");
        super.show();
    }
}
测试:
1  | public class Test {  | 
这个例子中每一个装饰对象都会调用自己装饰的那个对象,这个样子其实有点像责任链模式,不过责任链是将消息传递出去,而装饰模式是修饰已经已有的对象,一层一层的装饰.为对象动态的添加功能,最后形成一个完整的有用的对象.
在java中 输出输入流就是使用到了装饰器模式,在java中我们经常能见到这种写法.比如:1
2
3InputStream in = new FileInputStream("文件1");
BufferedInputStream bfi = new BufferedInputStream(in);
DataInputStream dis = new DataInputStream(bfi);
在这中写法中应该能够看出来这就是应用了装饰器模式,所有的这些输入流都继承InputStream类,通过一层一层的包装,来为输入流添加不同的功能.而他们每个类都有着上一层的一个实例对象,通过对此实例对象进行包装,就能够添加想要的功能.