概述
一般有两种方式可以实现给一个类或对象增加行为:
- 继承机制,使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法。但是这种方法是静态的,用户不能控制增加行为的方式和时机。
- 关联机制,即将一个类的对象嵌入另一个对象中,由另一个对象来决定是否调用嵌入对象的行为以便扩展自己的行为,我们称这个嵌入的对象为装饰器(Decorator)
定义: 装饰模式动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现给为灵活。
模式结构
- Component:抽象构件
- ConcreteComponent:具体构件
- Decorator:抽象装饰类
- ConcreteDecorator:具体装饰类
实例
问题: 简单的手机(SimplePhone)在接收到来电的时候,会发出声音来提醒主人,而现在我们需要为该手机添加一项功能,在接收来电的时候,除了有声音,还能产生震动(JarPhone),还可以得到更加高级的手机(ComplexPhone),来电时,它不仅能够发生,产生震动,而且有灯光闪烁提示,使用装饰模式来模拟手机功能的升级过程,要求绘制类图形编程模拟实现。
uml类图
代码:
public interface CellPhone {
public void receiveCall();
}
public class SimplePhone implements CellPhone{
@Override
public void receiveCall() {
System.out.print("来电响铃");
}
}
public class PhoneDecorator implements CellPhone{
private CellPhone cellPhone;
public PhoneDecorator(CellPhone cellPhone){
this.cellPhone = cellPhone;
}
@Override
public void receiveCall() {
cellPhone.receiveCall();
}
}
public class Vibrator extends PhoneDecorator {
public Vibrator(CellPhone cellPhone) {
super(cellPhone);
}
@Override
public void receiveCall() {
super.receiveCall();
System.out.print("震动");
}
}
public class Flashlight extends PhoneDecorator {
public Flashlight(CellPhone cellPhone) {
super(cellPhone);
}
@Override
public void receiveCall() {
super.receiveCall();
System.out.print("闪光灯");
}
}
public static void main(String[] args) {
CellPhone cellPhone = new SimplePhone();
//震动模式手机
CellPhone jarPhone = new Vibrator(new PhoneDecorator(cellPhone));
System.out.println("JarPhone:");
jarPhone.receiveCall();
CellPhone complexPhone = new Flashlight(jarPhone);
//完整模式手机
System.out.println("\nComplexPhone:");
complexPhone.receiveCall();
}
总结
- 与继承关系相比,关联关系的主要优势在于不会破坏类的封装性,而且继承是一种耦合度较大的静态关系,无法在程序运行时动态扩展。而关联关系的缺点是比继承关系要创建更多的对象。
- 使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的方式动态地给一个对象附加更多的责任。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。