行爲型模式:命令模式

LieBrother原文:
行爲型模式:命令模式java

景

十一大行爲型模式之三:命令模式。git

簡介

姓名 :命令模式github

英文名 :Command Pattern設計模式

價值觀 :軍令如山ide

我的介紹ui

Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or log requests,and support undoable operations.
將一個請求封裝成一個對象,從而讓你使用不一樣的請求把客戶端參數化,對請求排隊或者記錄請求日誌,能夠提供命令的撤銷和恢復功能。
(來自《設計模式之禪》)this

你要的故事

做爲一個程序猿,咱們天天都在經歷着命令模式,技術經理把需求任務分配給工程師開發,有時由於第三方或者其餘不可抗拒的因素致使需求中止開發。這種工做模式就是命令模式。好了,開始故事了。小明在 XX 科技公司作一個安靜的程序猿,有一天技術經理給他分配了一個任務:新增黑名單,也就是在他們系統的某個模塊裏面能夠手工對電話打黑名單標籤的功能。小明接到任務後就立馬開發,在開發了 2 天以後,由於戰略緣由,技術經理大明暫停了這個開發任務,接下來咱們經過非命令模式和命令模式 2 種代碼實現來體現這個過程。在這個場景中,爲了簡單,咱們假定技術經理大明手下只有小明一個開發人員。設計

非命令模式

非命令模式也就是不使用命令模式的代碼實現。代碼中,咱們出現了 Developer 開發人,開發同窗是接受技術經理傳達的任務,技術經理讓他開發哪一個需求就開發哪一個需求,若是項目有問題須要中斷,也須要技術經理評估後傳達給開發同窗,因此 Developer 有 2 個方法,分別是 develop() 開發需求和 suspend() 暫停需求。 Requirement 則爲需求類,TechnicalManager1 則爲技術經理類,他有一個方法 action(),經過這個方法來指定開發同窗開發任務或者暫停任務。日誌

public class NoCommandTest {

    public static void main(String[] args) {
        Developer xiaoMing = new Developer("小明");
        Requirement requirement = new Requirement("新增黑名單");
        TechnicalManager1 technicalManager2 = new TechnicalManager1("大明");
        technicalManager2.setDeveloper(xiaoMing);
        technicalManager2.action(requirement, "develop");
        System.out.println("開發了 2 天,需求變故,須要暫停。。。");
        technicalManager2.action(requirement, "suspend");
    }

}

/**
 * 開發人員
 */
class Developer {

    private String name;

    public Developer(String name) {
        this.name = name;
    }

    public void develop(Requirement requirement) {
        System.out.println(this.name + " 開始開發需求:" + requirement.getName());
    }

    public void suspend(Requirement requirement) {
        System.out.println(this.name + " 中止開發需求:" + requirement.getName());
    }

    public String getName() {
        return name;
    }

}

/**
 * 需求
 */
class Requirement {
    private String name;

    public Requirement(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

}

/**
 * 技術經理
 */
class TechnicalManager1 {

    private String name;

    private Developer developer;

    public TechnicalManager1(String name) {
        this.name = name;
    }

    public void setDeveloper(Developer developer) {
        this.developer = developer;
    }

    public void action(Requirement requirement, String type) {
        if ("develop".equals(type)) {
            this.developer.develop(requirement);
        } else if ("suspend".equals(type)) {
            this.developer.suspend(requirement);
        }
    }

}

打印結果:
小明 開始開發需求:新增黑名單
開發了 2 天,需求變故,須要暫停。。。
小明 中止開發需求:新增黑名單

經過代碼,咱們能夠發現技術經理和開發同窗是強依賴關係。若是技術經理下達了一個任務,要求小明寫一下週報,這時候得怎麼寫?是否是小明須要一個寫週報的方法,大明也須要新增一個處理事務類型?有沒有更好的方法讓技術經理不須要作任何改變?命令模式就來解決這個問題。code

命令模式

在這個例子中,無論大明叫小明作什麼事情,其實都是同樣的,就是下達任務命令,讓小明去執行命令。咱們能夠利用命令模式把下達任務這個抽象起來,當作父類,下達開發命令、下達暫停命令、下達寫週報等等都是不一樣的子命令。代碼以下。

public class CommandTest {

    public static void main(String[] args) {
        Developer xiaoMing = new Developer("小明");
        Command developCommand = new DevelopCommand(xiaoMing);
        Command suspendCommand = new SuspendCommand(xiaoMing);
        Requirement requirement = new Requirement("新增黑名單");
        TechnicalManager2 technicalManager = new TechnicalManager2("大明");
        technicalManager.setCommand(developCommand);
        technicalManager.action(requirement);
        System.out.println("開發了 2 天,需求變故,須要暫停。。。");
        technicalManager.setCommand(suspendCommand);
        technicalManager.action(requirement);

    }

}

/**
 * 命令
 */
abstract class Command {

    protected Developer developer;

    public Command(Developer developer) {
        this.developer = developer;
    }

    public abstract void execute(Requirement requirement);
}

/**
 * 開始開發
 */
class DevelopCommand extends Command {

    public DevelopCommand(Developer developer) {
        super(developer);
    }

    @Override
    public void execute(Requirement requirement) {
        this.developer.develop(requirement);
    }
}

/**
 * 開發中斷
 */
class SuspendCommand extends Command {

    public SuspendCommand(Developer developer) {
        super(developer);
    }

    @Override
    public void execute(Requirement requirement) {
        this.developer.suspend(requirement);
    }
}

/**
 * 技術經理
 */
class TechnicalManager2 {

    private String name;
    private Command command;

    public TechnicalManager2(String name) {
        this.name = name;
    }

    public void action(Requirement requirement) {
        this.command.execute(requirement);
    }

    public void setCommand(Command command) {
        this.command = command;
    }
}

打印結果:
小明 開始開發需求:新增黑名單
開發了 2 天,需求變故,須要暫停。。。
小明 中止開發需求:新增黑名單

代碼中用 Command 來抽象下達任務,而技術經理 TechnicalManager2 並無和 Developer 有直接的關係,而是 TechnicalManager2 和 Command 創建的聯繫,Command 和 Developer 創建了聯繫。這樣子把大明和小明的強依賴關係給剝離開,而新增一個下達寫週報的任務也很簡單,在 Developer 中新增一個處理寫週報的方法,新增一個寫週報的 Command 子類,就能夠了,TechnicalManager2 如上面所願不用修改。這就是完整的一個命令模式代碼。

代碼:
Command Pattern

總結

從文章中咱們就能夠看到,利用命令模式可以進行類的解耦,讓調用者和接受者沒有任何關係,也經過對行爲的抽象,讓新增其餘行爲變得清晰容易,也就是可擴展性大大增長

參考資料:《大話設計模式》、《設計模式之禪》

推薦閱讀:

公衆號之設計模式系列文章

但願文章對您有所幫助,設計模式系列會持續更新,感興趣的同窗能夠關注公衆號:LieBrother,第一時間獲取文章推送閱讀,也能夠一塊兒交流,交個朋友。

相關文章
相關標籤/搜索