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是在運行時對功能進行組合。