java23種設計模式-命令模式

在閻宏博士的《JAVA與模式》一書中開頭是這樣描述命令(Command)模式的:bash

  命令模式屬於對象的行爲模式。命令模式又稱爲行動(Action)模式或交易(Transaction)模式。ui

  命令模式把一個請求或者操做封裝到一個對象中。命令模式容許系統使用不一樣的請求把客戶端參數化,對請求排隊或者記錄請求日誌,能夠提供命令的撤銷和恢復功能。this

1 命令模式的結構

命令模式是對命令的封裝。命令模式把發出命令的責任和執行命令的責任分割開,委派給不一樣的對象。spa

每個命令都是一個操做:請求的一方發出請求要求執行一個操做;接收的一方收到請求,並執行操做。命令模式容許請求的一方和接收的一方獨立開來,使得請求的一方沒必要知道接收請求的一方的接口,更沒必要知道請求是怎麼被接收,以及操做是否被執行、什麼時候被執行,以及是怎麼被執行的。設計

命令容許請求的一方和接收請求的一方可以獨立演化,從而具備如下的優勢:日誌

  1. 命令模式使新的命令很容易地被加入到系統裏。code

  2. 容許接收請求的一方決定是否要否決請求。cdn

  3. 能較容易地設計一個命令隊列。對象

  4. 能夠容易地實現對請求的撤銷和恢復。blog

  5. 在須要的狀況下,能夠較容易地將命令記入日誌。

下面以一個示意性的系統,說明命令模式的結構。

命令模式涉及到五個角色,它們分別是:

  • **客戶端(Client)角色:**建立一個具體命令(ConcreteCommand)對象並肯定其接收者。

 ●  **命令(Command)角色:**聲明瞭一個給全部具體命令類的抽象接口。

 ●  **具體命令(ConcreteCommand)角色:**定義一個接收者和行爲之間的弱耦合;實現execute()方法,負責調用接收者的相應操做。execute()方法一般叫作執行方法。

 ●  **請求者(Invoker)角色:**負責調用命令對象執行請求,相關的方法叫作行動方法。

 ●  **接收者(Receiver)角色:**負責具體實施和執行一個請求。任何一個類均可以成爲接收者,實施和執行請求的方法叫作行動方法。

2 代碼示例

以開發一個項目爲例,這個項目的成員分工也是採用了常規的分工方式,分爲需求組(Requirement Group,簡稱 RG)、美工組(Page Group,簡稱 PG)、代碼組(咱們內部還有一個比較優雅的名字:邏輯實現組,這裏使用你們常常稱呼的名稱吧,英文縮寫叫 Code Group,簡稱 CG)。

public abstract class Group {

    //你要和那個組討論,你首先要找到這個組
    public abstract void find();
    //被要求增長功能
    public abstract void add();
    //被要求刪除功能
    public abstract void delete();
    //被要求修改功能
    public abstract void change();
    //被要求給出全部的變動計劃
    public abstract void plan();

}
複製代碼
public class PageGroup extends Group {

    //首先這個美工組應該被找到吧,要不你跟誰談?
    public void find() {
        System.out.println("找到美工組...");
    }
    //美工被要求增長一個頁面
    public void add() {
        System.out.println("客戶要求增長一個頁面...");
    }
    //客戶要求對現有界面作修改
    public void change() {
        System.out.println("客戶要求修改一個頁面...");
    }
    //甲方是老大,要求刪除一些頁面
    public void delete() {
        System.out.println("客戶要求刪除一個頁面...");
    }
    //全部的增刪改那要給出計劃呀
    public void plan() {
        System.out.println("客戶要求頁面變動計劃...");
    }

}
複製代碼
public class CodeGroup extends Group {

    //客戶要求代碼組過去和他們談
    public void find() {
        System.out.println("找到代碼組...");
    }
    //客戶要求增長一項功能
    public void add() {
        System.out.println("客戶要求增長一項功能...");
    }
    //客戶要求修改一項功能
    public void change() {
        System.out.println("客戶要求修改一項功能...");
    }
    //客戶要求刪除一項功能
    public void delete() {
        System.out.println("客戶要求刪除一項功能...");
    }
    //客戶要求出變動計劃
    public void plan() {
        System.out.println("客戶要求代碼變動計劃...");
    }

}
複製代碼
public class RequirementGroup extends Group {

    //客戶要求需求組過去和他們談
    public void find() {
        System.out.println("找到需求組...");
    }
    //客戶要求增長一項需求
    public void add() {
        System.out.println("客戶要求增長一項需求...");
    }
    //客戶要求修改一項需求
    public void change() {
        System.out.println("客戶要求修改一項需求...");
    }
    //客戶要求刪除一項需求
    public void delete() {
        System.out.println("客戶要求刪除一項需求...");
    }
    //客戶要求出變動計劃
    public void plan() {
        System.out.println("客戶要求需求變動計劃...");
    }
}
複製代碼

這時候客戶須要修改需求了,定義出命令類:

public abstract class Command {

    //把三個組都定義好,子類能夠直接使用
    protected RequirementGroup rg = new RequirementGroup(); //需求組
    protected PageGroup pg = new PageGroup(); //美工組
    protected CodeGroup cg = new CodeGroup(); //代碼組;
    //只要一個方法,你要我作什麼事情
    public abstract void execute();

}
複製代碼
//增長一項需求
public class AddRequirementCommand extends Command {

    //執行增長一項需求的命令
    public void execute() {
        //找到需求組
        super.rg.find();
        //增長一份需求
        super.rg.add();
        //給出計劃
        super.rg.plan();
    }
}
複製代碼
//刪除一個頁面的命令
public class DeletePageCommand extends Command {

    //執行刪除一個頁面的命令
    public void execute() {
        //找到頁面組
        super.pg.find();
        //刪除一個頁面
        super.rg.delete();
        //給出計劃
        super.rg.plan();
    }
}
複製代碼

有了定義好得需求,咱們須要一個跟客戶對接得對接人:

public class Invoker {

    //什麼命令
    private Command command;
    //客戶發出命令
    public void setCommand(Command command){
        this.command = command;
    }
    //執行客戶的命令
    public void action(){
        this.command.execute();
    }
}
複製代碼

最後客戶溝通修改需求:

public class Client {

    public static void main(String[] args) {
        //定義咱們的接頭人
        Invoker xiaoSan = new Invoker(); //接頭人就是我小三
        //客戶要求增長一項需求
        System.out.println("-------------客戶要求增長一項需求-----------------");
        //客戶給咱們下命令來
        Command command = new AddRequirementCommand();
        //接頭人接收到命令
        xiaoSan.setCommand(command);
        //接頭人執行命令
        xiaoSan.action();
    }

}
複製代碼

3 總結

命令模式比較簡單,可是在項目中使用是很是頻繁的,封裝性很是好,由於它把請求方(Invoker)和執 行方(Receiver)分開了,擴展性也有很好的保障。可是,命令模式也是有缺點的,你看 Command 的子類沒 有,那個若是我要寫下去的可不是幾個,而是幾十個,這個類膨脹的很是多,這個就須要你們在項目中本身考慮 使用了。

相關文章
相關標籤/搜索