天天看點

C#設計模式(15)——指令模式(Command Pattern)一、前言二、指令模式的介紹三、.NET中指令模式的應用(引用TerryLee)四、指令模式的适用場景五、指令模式的優缺點六、總結

  之前一直在忙于工作上的事情,關于設計模式系列一直沒更新,最近項目中發現,對于設計模式的了解是必不可少的,當然對于設計模式的應用那更是重要,可以說是否懂得應用設計模式在項目中是衡量一個程式員的技術水準,因為對于一個功能的實作,進階工程師和初級工程師一樣都會實作,但是差別在于它們實作功能的可擴充和可維護性,也就是代碼的是否“優美”、可讀。但是,要更好地應用,首先就必須了解各種設計模式和其應用場景,是以我還是希望繼續完成設計模式這個系列,希望通過這種總結的方式來加深自己設計模式的了解。

指令模式屬于對象的行為型模式。指令模式是把一個操作或者行為抽象為一個對象中,通過對指令的抽象化來使得發出指令的責任和執行指令的責任分隔開。指令模式的實作可以提供指令的撤銷和恢複功能。

  既然,指令模式是實作把發出指令的責任和執行指令的責任分割開,然而中間必須有某個對象來幫助發出指令者來傳達指令,使得執行指令的接收者可以收到指令并執行指令。例如,開學了,院上司說計算機學院要進行軍訓,計算機學院的學生要跑1000米,院上司的話也就相當于一個指令,他不可能直接傳達給到學生,他必須讓教官來發出指令,并監督學生執行該指令。在這個場景中,發出指令的責任是屬于學院上司,院上司充當與指令發出者的角色,執行指令的責任是屬于學生,學生充當于指令接收者的角色,而教官就充當于指令的發出者或指令請求者的角色,然而指令模式的精髓就在于把每個指令抽象為對象。進而指令模式的結構如下圖所示:

C#設計模式(15)——指令模式(Command Pattern)一、前言二、指令模式的介紹三、.NET中指令模式的應用(引用TerryLee)四、指令模式的适用場景五、指令模式的優缺點六、總結

從指令模式的結構圖可以看出,它涉及到五個角色,它們分别是:

客戶角色:發出一個具體的指令并确定其接受者。

指令角色:聲明了一個給所有具體指令類實作的抽象接口

具體指令角色:定義了一個接受者和行為的弱耦合,負責調用接受者的相應方法。

請求者角色:負責調用指令對象執行指令。

接受者角色:負責具體行為的執行。

  現在,讓我們以上面的軍訓的例子來實作一個指令模式,在實作之前,可以參考下指令模式的結構圖來分析下實作過程。

  軍訓場景中,具體的指令即是學生跑1000米,這裡學生是指令的接收者,教官是指令的請求者,院上司是指令的發出者,即用戶端角色。要實作指令模式,則必須需要一個抽象指令角色來聲明約定,這裡以抽象類來來表示。指令的傳達流程是:

  指令的發出者必須知道具體的指令、接受者和傳達指令的請求者,對應于程式也就是在用戶端角色中需要執行個體化三個角色的執行個體對象了。

  指令的請求者負責調用指令對象的方法來保證指令的執行,對應于程式也就是請求者對象需要有指令對象的成員,并在請求者對象的方法内執行指令。

  具體指令就是跑1000米,這自然屬于學生的責任,是以是具體指令角色的成員方法,而抽象指令類定義這個指令的抽象接口。

  有了上面的分析之後,具體指令模式的實作代碼如下所示:

 在ASP.NET的MVC模式中,有一種叫Front Controller的模式,它分為Handler和Command樹兩個部分,Handler處理所有公共的邏輯,接收HTTP Post或Get請求以及相關的參數并根據輸入的參數選擇正确的指令對象,然後将控制權傳遞到Command對象,由其完成後面的操作,這裡面其實就是用到了Command模式。

C#設計模式(15)——指令模式(Command Pattern)一、前言二、指令模式的介紹三、.NET中指令模式的應用(引用TerryLee)四、指令模式的适用場景五、指令模式的優缺點六、總結

     Front Controller 的處理程式部分結構圖

C#設計模式(15)——指令模式(Command Pattern)一、前言二、指令模式的介紹三、.NET中指令模式的應用(引用TerryLee)四、指令模式的适用場景五、指令模式的優缺點六、總結

    Front Controller的指令部分結構圖

Handler 類負責處理各個 Web 請求,并将确定正确的 Command 對象這一職責委派給 CommandFactory 類。當 CommandFactory 傳回 Command 對象後,Handler 将調用 Command 上的 Execute 方法來執行請求。具體的實作如下

C#設計模式(15)——指令模式(Command Pattern)一、前言二、指令模式的介紹三、.NET中指令模式的應用(引用TerryLee)四、指令模式的适用場景五、指令模式的優缺點六、總結
C#設計模式(15)——指令模式(Command Pattern)一、前言二、指令模式的介紹三、.NET中指令模式的應用(引用TerryLee)四、指令模式的适用場景五、指令模式的優缺點六、總結

View Code

   在下面的情況下可以考慮使用指令模式:

系統需要支援指令的撤銷(undo)。指令對象可以把狀态存儲起來,等到用戶端需要撤銷指令所産生的效果時,可以調用undo方法吧指令所産生的效果撤銷掉。指令對象還可以提供redo方法,以供用戶端在需要時,再重新實作指令效果。

系統需要在不同的時間指定請求、将請求排隊。一個指令對象和原先的請求發出者可以有不同的生命周期。意思為:原來請求的發出者可能已經不存在了,而指令對象本身可能仍是活動的。這時指令的接受者可以在本地,也可以在網絡的另一個位址。指令對象可以串行地傳送到接受者上去。

如果一個系統要将系統中所有的資料消息更新到日志裡,以便在系統崩潰時,可以根據日志裡讀回所有資料的更新指令,重新調用方法來一條一條地執行這些指令,進而恢複系統在崩潰前所做的資料更新。

系統需要使用指令模式作為“CallBack(回調)”在面向對象系統中的替代。Callback即是先将一個方法注冊上,然後再以後調用該方法。

   指令模式使得指令發出的一個和接收的一方實作低耦合,進而有以下的優點:

指令模式使得新的指令很容易被加入到系統裡。

可以設計一個指令隊列來實作對請求的Undo和Redo操作。

可以較容易地将指令寫入日志。

可以把指令對象聚合在一起,合成為合成指令。合成指令式合成模式的應用。

  指令模式的缺點:

使用指令模式可能會導緻系統有過多的具體指令類。這會使得指令模式在這樣的系統裡變得不實際。

   指令模式的實作要點在于把某個具體的指令抽象化為具體的指令類,并通過加入指令請求者角色來實作将指令發送者對指令執行者的依賴分割開,在上面軍訓的例子中,如果不使用指令模式的話,則指令的發送者将對指令接收者是強耦合的關系,實作代碼如下:

  到這裡,本章的内容就介紹結束了,在下一章将繼續為大家分享下我對疊代器模式的了解。

繼續閱讀