Decorator模式也叫装饰模式,是由GoF提出的23种软件设计模式的一种。Decorator模式是构造型的设计模式之一,它为类的实例对象动态追加附加功能,就好像装饰了对象的行为。
Decorator模式是构造型的设计模式之一,它可以动态地改变一个对象方法的行为。
Component
原有类的接口
ConcreteComponent
功能实现类。Component的具体实现类
Decorator
装 饰抽象类。与ConcreteComponent一样都继承了Component接口,但实现的方式与ConcreteComponent有区别。 ConcreteComponent通过单纯继承的方式来实现;而Decorator则通过对Component对象的封装与动作委让方式来实现。
下面是一个典型的Decorator的代码为:
清单1
public class Decorator implement Component {
Component component;
public Decorator(Component component) {
this.component = component;
}
public void doSomething() {
...
this.component.doSomething();
...
}
}
ConcreteDecoratorA 与 ConcreteDecorator
具体的装饰类。Decorator的具体实现类
为什么要如清单1所示去构造类的关系呢?或者说,为什么不直接使用一般的继承或其他方法呢?我们通过下面的范例来回答这个问题。
比如,汽车上色的过程:
要对从工厂刚出来的同一种汽车进行上色,
首先给汽车上相同的底色;
然后根据不同的要求,进行下面的操作:
有时希望上黄色;
有时希望上红色;
有时希望先上黄色,再上红色;
有时希望先上红色,再上黄色;
如果要在汽车类中完成上面的功能,不管是通过横向扩展(为类增加方法)还是纵向扩展(子类),都很难设计出柔软的可扩展的类结构。
上述过程用Decorator模式来描述:
汽车抽象类Car相当于Decorator模式类图中的Component,该接口定义了一个makeColor()方法用来给汽车上色
卡车类Truck相当于ConcreteComponent
上色抽象类MakeColorCar相当于Decorator
上黄色类MakeYellowColorCar与上红色类MakeRedColorCar就相当于ConcreteDecorator
代码:
- public class Client {
- //测试类
- public static void main(String[] args) {
- //生产一辆卡车1(基本色)
- System.out.println("--Truck 1--" );
- Car truck = new Truck();
- MakeColorCar yellowCar = new MakeYellowColorCar(truck);
- MakeColorCar redCar = new MakeRedColorCar(yellowCar);
- redCar.makeColor();
- //生产一辆卡车2(基本色)
- System.out.println("--Truck 2--" );
- Car truck2 = new Truck();
- MakeColorCar redCar2 = new MakeRedColorCar(truck2);
- MakeColorCar yellowCar2 = new MakeYellowColorCar(redCar2);
- yellowCar2.makeColor();
- }
- }
- /**
- * Component class & subclass
- *
- */
- interface Car {
- //上色
- public void makeColor();
- }
- class Truck implements Car {
- public void makeColor() {
- System.out.println("Make basic-color for truck:" );
- }
- }
- /**
- * Decorator class & subclass
- *
- */
- class MakeColorCar implements Car {
- protected Car car;
- public MakeColorCar(Car car) {
- this .car = car;
- }
- public void makeColor() {
- this .car.makeColor();
- }
- }
- class MakeYellowColorCar extends MakeColorCar {
- public MakeYellowColorCar(Car car) {
- super (car);
- }
- public void makeColor() {
- super .makeColor();
- System.out.println("Add yellow." );
- }
- }
- class MakeRedColorCar extends MakeColorCar {
- public MakeRedColorCar(Car car) {
- super (car);
- }
- public void makeColor() {
- super .makeColor();
- System.out.println("Add red." );
- }
- }
public class Client {
//测试类
public static void main(String[] args) {
//生产一辆卡车1(基本色)
System.out.println("--Truck 1--");
Car truck = new Truck();
MakeColorCar yellowCar = new MakeYellowColorCar(truck);
MakeColorCar redCar = new MakeRedColorCar(yellowCar);
redCar.makeColor();
//生产一辆卡车2(基本色)
System.out.println("--Truck 2--");
Car truck2 = new Truck();
MakeColorCar redCar2 = new MakeRedColorCar(truck2);
MakeColorCar yellowCar2 = new MakeYellowColorCar(redCar2);
yellowCar2.makeColor();
}
}
/**
* Component class & subclass
*
*/
interface Car {
//上色
public void makeColor();
}
class Truck implements Car {
public void makeColor() {
System.out.println("Make basic-color for truck:");
}
}
/**
* Decorator class & subclass
*
*/
abstract class MakeColorCar implements Car {
protected Car car;
public MakeColorCar(Car car) {
this.car = car;
}
public void makeColor() {
this.car.makeColor();
}
}
class MakeYellowColorCar extends MakeColorCar {
public MakeYellowColorCar(Car car) {
super(car);
}
public void makeColor() {
super.makeColor();
System.out.println("Add yellow.");
}
}
class MakeRedColorCar extends MakeColorCar {
public MakeRedColorCar(Car car) {
super(car);
}
public void makeColor() {
super.makeColor();
System.out.println("Add red.");
}
}
执行Client,输出结果:
C:/Decorator>java Client
--Truck 1--
Make basic-color for truck:
Add yellow.
Add red.
--Truck 2--
Make basic-color for truck:
Add red.
Add yellow.
C:/Decorator>
对于类的不同对象truck1与truck2,我们可以应用Decorator模式改变其行为:我们为truck1先上底色,然后上黄色,再上红色;但为truck2先上底色,然后上红色,再上黄色。
有关Adapter模式和Builder模式的介绍,请参考下面2篇文章:
设计模式之Adapter - 适配器模式
设计模式之Bridge - 桥接模式
与Decorator模式一样,它们具有以下相同点 :
- 都是构造型的设计模式
- 都是通过新类对原有类的封装(继承或委让的方式)
它们的不同点 :
- 对象:Adapter强调外部接口,Bridge强调内部实现。Adapter通过提供新的接口形式隐蔽对原有类(功能)的调用,Bridge把同一事物的抽象与具体行为分离。
- 封装:Decorator可以不用修改原有对象接口,为对象增加新的功能或改变其行为;Adapter如需增加功能,则需修改接口。
举例来说,比如有一样东西,它提供a,b,c等功能,
采用Adapter模式来实现的话,就等于告诉用户,我有a, b, c等功能,你可以使用,但这些功能都是通过外部(调用其它类)实现的。
Bridge则这样告诉用户:有一样东西A,提供某项功能,这项功能可能是a, 或b, 或c功能,用户自己在使用A时,可以选择让A组合a功能(A+a),或b功能(A+b),或c功能(A+c)。
Decorator则是这样:有一样东西A,提供一个基本功能a。另外给它做了具有功能b的封套B,具有功能c的封套C。你可以在使用A时,把A装进B,或C里,这样就具有a+b,或a+c功能了,甚至还可以把装有A的B装入到C里,这样便具有a+b+c功能了。