1、装饰模式(Decorator):
动态地给一个对象天剑一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。
装饰模式是以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
动态方式给一个对象附加更多的功能。
装饰模式可以在不创造更多的子类的情况下扩张对象的功能。
2、装饰模式的角色:
抽象构件角色(Component):定义一个对象接口,可以给这些对象动态地添加职责。 具体构件角色(Concrete Component):定义了一个具体的对象,也可以给这个对象添加一些职责。
装饰角色(Decorator):装饰抽象类。
具体装饰角色(Concrete Decorator):具体的装饰对象,起到给Component添加职责的功能。
3、装饰模式的结构图:
4、装饰模式的特点:
装饰角色和构件角色有相同的接口,这样客户端就可以用和构件角色相同的方式和装饰角色交互了。
装饰角色包含一个真实对象的引用。
来自客户端的请求,通过装饰对象接收,转发给真实的构件角色。
装饰对象可以在转发请求之前或之后附加功能。在面向对象设计中,通常是通过继承来实现的。而使用了装饰模式,就可以不用修改给定对象的结构就可以实现了。
5、装饰模式和继承的比较:
装饰模式:
可以扩展对象的功能而不需要额外创建子类。
可以动态添加功能。
防止由于子类而导致复杂的继承结构,更加灵活,方便客户端对功能进行组合使用。
继承:
扩展类对象的功能,需要实现相应的子类。
是静态的,导致出现很多子类,复杂的继承结构,缺乏灵活性。
6、装饰模式在JavaIO流系统中的使用
下面就通过一个装饰模式的基本实现说明装饰模式在JavaIO流系统中的使用。
6.1、首先创建抽象构件角色,这个接口相当于JavaIO中的java.io.InputStream:
1
2
3
4
5
6
7/**
* 抽象构件角色
*/
public interface Component{
public void operation();
}
6.2、创建一个具体的构件角色实现构件角色接口,这个类相当于JavaIO流的任何一个节点流类,如:java.io 类 FileInputStream:
/**
具体构件角色
*/
public class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("具体的功能");
}
}
6.3、创建一个装饰角色实现抽象构件角色,这个类相当于JavaIO中的过滤流java.io 类 FilterInputStream:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16/**
* 装饰角色
*/
public class Decorator implements Component{
private Component component;
public Decorator(Component component){
this.component = component;
}
@Override
public void operation(){
component.operation();
}
}
6.4、创建一个具体的装饰角色继承装饰角色,可以对继承下来的方法封装其他的操作,这个类相当于JavaIO中的任何一个过滤流,如:java.io 类 BufferedInputStream:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/**
* 具体装饰角色
*/
public class ConcreteDecorator extends Decorator{
public ConcreteDecorator(Component component){
super(component);
}
@Override
public void operation(){
super.operation();
this.addBehavior();
}
private void addBehavior(){
System.out.println("ok");
}
}
6.5、客户端调用代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14public class Client{
/**
* @param args
*/
public static void main(String[] args){
//节点流
Component component = new ConcreteComponent();
//过滤流
Component component2 = new ConcreteDecorator(component);
component2.operation();
}
}