(8)設計模式之裝飾模式(結構型模式)

聲明:以下都是博主淺薄的經驗之談,歡迎大家學習交流

使用場景

  • 我們在做系統設計的時候,一個非常重要的工作就是把大系統進行逐一的分解在分解。譬如用戶管理模塊、支付模塊,但是每一個模塊的某些業務功能都是通用。如在執行業務方法之前需進行這個操作:記錄業務方法的操作日誌;統計業務方法的執行時間;業務方法開始前開啓事務,方法結束之後提交事務,方法異常回滾事務。
  • 於是就會產生如下類似的僞代碼
public void PayService{
    public Response execute()
    {
        logger.debug("....");//記錄日誌
        RecordTimeUtiles.startTime();//記錄業務方法執行時間
        //執行業務方法的的代碼...
        //......
        //......
        RecordTimeUtiles.endTime();
    }
}
  • 雖然這樣的代碼實現了功能,但是可想而知後續增加更多的業務功能方法,也都是需要重複以上的代碼。

  • 此時可以應用模板方法設計模式來解決以上大部分代碼重複的問題。

  • AbstractService.java
public abstract class AbstractService{
    public void execute(){
        logger.debug("....");//記錄日誌
        RecordTimeUtiles.startTime();//記錄業務方法執行時間
        //執行業務方法的的代碼...
        //......
        payServiceExecute();
        //......
        RecordTimeUtiles.endTime();

    }
    public abstract Response payServiceExecute();
}
  • PayService.java
public class PayService extends AbstractService{
    public Response payServiceExecute(){
        //執行業務方法的的代碼...
        //......
        //......
    }
}
  • 此時父類AbstractService.java 已經將原先的記錄日誌、方法執行時間等重複性的代碼都寫好了,而子類PayService.java只需要通過實現父類的抽象方法【payServiceExecute】去實現自己需要的業務功能代碼即可!
    調用的方式很簡單如下:
    AbstractService as = new PayService();
    as.execute();
  • 缺點:這樣的方式最大的缺陷就是父類定義了一切,子類要毫無保留的去服從。什麼執行順序啥的,都不是子類所能控制的,假如某個子類不要統計方法的時間只要記錄日誌,此時這樣的設計方法就無能爲力了。

裝飾模式

  • 如果利用裝飾模式,針對上面問題將會帶來更大的靈活性,且看!

  • Service.java

    public interface Service{
        Response execute();
    }
  • LogDecorator.java
public class LogDecorator implements Service{
private Service service;
public LogDecorator (Service service){
        this.service = service;
    }
    public Response execute(){
        logger.debug("....");//記錄日誌
        this.service.execute();
    }
}
  • RecordTimeDecorator.java
public class RecordTimeDecorator implements Service{
private Service service;
public RecordTimeDecorator(Service service){
        this.service = service;
    }
    public Response execute(){
      RecordTimeUtiles.startTime();//記錄業務方法執行時間
        this.service.execute();
      RecordTimeUtiles.endTime();
    }
}
  • PayService.java
public class PayService implements Service{
    public Response execute(){
        //執行業務方法的的代碼...
        //......
    }
}
  • 調用方式
//場景一:只需要記錄日誌
Service service = new LogDecorator(new PayService());
service.execute();
//場景二:只需要記錄業務方法執行的時間
Service  service = new RecordTimeDecorator(new PayService());
service.execute();
//場景三:需要記錄日誌;記錄業務方法執行的時間
Service  service = new RecordTimeDecorator(new LogDecorator(new PayService()));
service.execute();
  • 是不是很靈活,我們要什麼就包裝什麼。而且還可能指定包裝的順序從而實現代碼執行的順序。

聲明:以上都是博主淺薄的經驗之談,歡迎大家學習交流

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章