Java设计模式(七)
-------装饰模式
概述
在软件系统中,有时候我们会使用继承来扩展对象的功能,但是由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增 多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子 类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低?这就是本文要讲的Decorator模式。
意图
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
实现
模拟示例
我们模拟一个手机的例子,假设普通手机只有呼叫号码和发送短消息的功能,我们现在为手机增加蓝伢检测,扩展它发送短消的功能,在发送短消息时先检测蓝伢,然后再通过蓝伢发送消息。
传统继承方式
父类
public class CellPhone { public void call() { System.out.println("打了一个电话"); } public void sendMessage() { System.out.println("发一个短消息"); } } |
定义扩展功能接口
/** * 增加蓝牙功能 * * @author Administrator * */ public interface BlueToothFunction { public void blueToothSendFile();
} |
子类(扩展类)
public class BlueToothCellPhone extends CellPhone implements BlueToothFunction { @Override public void sendMessage() { // TODO Auto-generated method stub this.blueToothSendFile(); super.sendMessage(); } @Override public void blueToothSendFile() { // TODO Auto-generated method stub System.out.println("检测蓝牙状态,发送文件..."); } } |
装饰模式的应用
角色
抽象功能角色(Component):
定义一个抽象接口,以规范准备接收附加责任的对象。
public interface AbstractCellPhoneFunction { public void call(); public void sendMessage(); } |
被装饰者角色:
这是被装饰者,定义一个将要被装饰增加功能的类。
public class CellPhone implements AbstractCellPhoneFunction { public void call() { System.out.println("打了一个电话"); } public void sendMessage() { System.out.println("发一个短消息"); }; } |
抽象装饰角色(Decorator):
持有一个构件对象的实例,并定义了抽象构件定义的接口。
public abstract class AbstractDecoratorCellPhone implements AbstractCellPhoneFunction { private AbstractCellPhoneFunction phone; public AbstractDecoratorCellPhone(AbstractCellPhoneFunction phone){ this.phone=phone; } @Override public void call() { // TODO Auto-generated method stub phone.call(); } @Override public void sendMessage() { // TODO Auto-generated method stub phone.sendMessage(); } } |
具体装饰角色(Concrete Decorator):
负责给构件添加增加的功能。
public class BlueToothCellPhone extends AbstractDecoratorCellPhone { public BlueToothCellPhone(AbstractCellPhoneFunction phone) { super(phone); } @Override public void call() { // TODO Auto-generated method stub super.call(); } @Override public void sendMessage() { // TODO Auto-generated method stub this.blueToothFunction(); super.sendMessage(); } private void blueToothFunction() { System.out.println("检测蓝牙状态,发送信息..."); } } |
客户端调用
public class MyTest { /** * @param args */ public static void main(String[] args) { AbstractCellPhoneFunction af = new CellPhone(); af.sendMessage(); //System.out.println("/n"); AbstractCellPhoneFunction blueToothCellPhone = new BlueToothCellPhone(af); blueToothCellPhone.sendMessage(); } }
打印结果: 发一个短消息 检测蓝牙状态,发送信息... 发一个短消息 |
总结
装饰模式用如果要用一句话来总结,那么它的总体思想就是:以动态的方式,在接口不变的情况下,在接口方法的前后扩展功能。
通过采用组合、而非继承的手法,Decorator模式实现了在运行时动态的扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了单独使用继承带来的“灵活性差”和“多子类衍生问题”。
当我们实例化一个Component对象后,要给这个对象扩展功能,这时我们把这个Component对象当作参数传给Decorator的子类的构造函数——也就是扩展方法的功能类。
Decorator模式并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义。Decorator是在运行时对功能进行组合。