装饰模式
适用范围:
1. 需要扩展一个类的功能,或给一个类添加附加职责。
2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
主要角色:
(1)抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
(2)具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
(3)装饰(Decorator)角色:持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口。
(4)具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加的责任。
示例程序:
1)抽象构件
package com.medivh.dec;
public interface Mum
{
public void doSomething();
}
2)具体构件 (实现了抽象构件)
package com.medivh.dec;
public class Son implements Mum
{
public void doSomething()
{
System.out.println("Son");
}
}
3)装饰角色
package com.medivh.dec;
public class A extends Son
{
private Mum s;
public A(Mum mum)
{
this.s = mum;
}
public void doSomething()
{
s.doSomething();
}
}
4)具体装饰角色(继承于 装饰角色)
package com.medivh.dec;
public class A1 extends A
{
public A1(Mum mum)
{
super(mum);
}
public void doSomething()
{
super.doSomething();
this.doAnotherThing();
}
public void doAnotherThing()
{
System.out.println("A1");
}
}
package com.medivh.dec;
public class A2 extends A
{
public A2(Mum mum)
{
super(mum);
}
public void doSomething()
{
super.doSomething();
this.doAnotherThing();
}
public void doAnotherThing()
{
System.out.println("A2");
}
}
5)测试类
package com.medivh.dec;
public class Test
{
public static void main(String[] args)
{
Mum t = new Son();
t.doSomething();
System.out.println("*******************************");
Mum a = new A(new Son());
a.doSomething();
System.out.println("*******************************");
Mum a1 = new A1(new Son());
a1.doSomething();
System.out.println("*******************************");
Mum a2 = new A2(new Son());
a2.doSomething();
System.out.println("*******************************");
Mum m1 = new A2(new A1(new Son()));
m1.doSomething();
System.out.println("*******************************");
Mum m2 = new A1(new A2(new Son()));
m2.doSomething();
}
}
6)测试结果
Son
*******************************
Son
*******************************
Son
A1
*******************************
Son
A2
*******************************
Son
A1
A2
*******************************
Son
A2
A1
原则
1. 多用组合,少用继承。
利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。
2. 类应设计的对扩展开放,对修改关闭。