設計模式之命令模式

類圖結構

image.png
  • Receiver接受者角色:該角色就是干活的角色搀庶,命令傳遞到這里是應該被執(zhí)行的
  • Command命令角色:需要執(zhí)行的所有命令都在這里聲明
  • Invoker調用者角色:接收到命令鞍时,并執(zhí)行命令
//通用Receiver類
public abstract class Receiver {
    public abstract void doSomething();
}

//具體Receiver類
public class ConcreteReciver1 extends Receiver{ 
    //每個接收者都必須處理一定的業(yè)務邏輯 
    public void doSomething(){ } 
} 
public class ConcreteReciver2 extends Receiver{ 
    //每個接收者都必須處理一定的業(yè)務邏輯 
    public void doSomething(){ } 
}

//抽象Command類
public abstract class Command {
    public abstract void execute();
}

//具體的Command類
public class ConcreteCommand1 extends Command { 
    //對哪個Receiver類進行命令處理 
    private Receiver receiver; 
    //構造函數(shù)傳遞接收者 
    public ConcreteCommand1(Receiver _receiver){
        this.receiver = _receiver; 
    } 

    //必須實現(xiàn)一個命令 
    public void execute() { 
    //業(yè)務處理 
        this.receiver.doSomething(); 
    } 
} 

public class ConcreteCommand2 extends Command { 
    //哪個Receiver類進行命令處理 
    private Receiver receiver; 
    //構造函數(shù)傳遞接收者 
    public ConcreteCommand2(Receiver _receiver){
        this.receiver = _receiver; 
    } 
    //必須實現(xiàn)一個命令 
    public void execute() { 
        //業(yè)務處理 
        this.receiver.doSomething();
    } 
}

//調用者Invoker類
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 invoker = new Invoker();
        Receiver receiver = new ConcreteReceiver1();
        
        Command command = new ConcreteCommand1(receiver);
        invoker.setCommand(command);
        invoker.action();
    }
}

實例2

|現(xiàn)在比較火的小米手機,可以當作遙控器控制多種不同的家電,手機發(fā)送命令妓布,不同的電器接收到后執(zhí)行酌伊。


image.png
  • Command類
public interface Command {
    public void execute();
    public void undo();
}
  • 開燈命令
public class LightOnCommand implements Command {
    private Light light;

    LightOnCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.on();
    }

    public void undo() {
        light.off();
    }
}
  • 開電視命令
public class TVOnCommand implements Command {
    private TV tv;

    public TVOnCommand(TV tv) {
        this.tv = tv;
    }

    public void execute() {
        tv.on();
    }

    public void undo() {
        tv.off();
    }
}
  • 家用電器接口類
public interface HouseholdAppliances {
    public void on();
    public void off();
}
  • 電視類
public class TV implements HouseholdAppliances {
    public void on() {
        System.out.println("the TV on");
    }

    public void off() {
        System.out.println("the TV off");
    }
}
  • 電燈類
public class Light implements HouseholdAppliances{
    public void on() {
        System.out.println("the light on");
    }

    public void off() {
        System.out.println("the light off");
    }
}
  • 手機控制器類
public class MiPhone {
    ArrayList commands;

    public MiPhone() {
        commands = new ArrayList();
    }

    public void setCommand(Command command) {
        commands.add(command);
    }

    public void onButtonWasPushed(int slot) {
        ((Command)commands.get(slot-1)).execute();
    }

    public static void main(String[] args) {
        MiPhone miPhone = new MiPhone();
        //創(chuàng)建電器
        Light light = new Light();
        TV tv = new TV();
        //創(chuàng)建命令
        LightOnCommand lightOnCommand = new LightOnCommand(light);
        TVOnCommand tvOnCommand = new TVOnCommand(tv);
        //給小米手機設置命令
        //設置第一個按鈕為開燈
        miPhone.setCommand(lightOnCommand);
        //設置第二個按鈕為開電視
        miPhone.setCommand(tvOnCommand);

        //開燈
        miPhone.onButtonWasPushed(1);
        //開電視
        miPhone.onButtonWasPushed(2);
    }
}
  • 運行結果


    image.png

應用

優(yōu)點

  • 類間解耦:調用者角色與接收者角色之間沒有任何依賴關系舌厨,調用者實現(xiàn)功能時只需調用Command 抽象類的execute方法就可以浴鸿,不需要了解到底是哪個接收者執(zhí)行井氢。
  • 可擴展性:Command的子類可以非常容易地擴展,而調用者Invoker和高層次的模塊Client不產生嚴 重的代碼耦合岳链。
  • 命令模式結合其他模式會更優(yōu)秀:命令模式可以結合責任鏈模式花竞,實現(xiàn)命令族解析任務;結合模板方法模式掸哑,則可以減少 Command子類的膨脹問題

缺點

  • 命令模式也是有缺點的约急,請看Command的子類:如果有N個命令,問題就出來 了举户,Command的子類就可不是幾個烤宙,而是N個,這個類膨脹得非常大俭嘁,這個就需要讀者在項 目中慎重考慮使用躺枕。
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市供填,隨后出現(xiàn)的幾起案子拐云,更是在濱河造成了極大的恐慌,老刑警劉巖近她,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叉瘩,死亡現(xiàn)場離奇詭異,居然都是意外死亡粘捎,警方通過查閱死者的電腦和手機薇缅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來攒磨,“玉大人泳桦,你說我怎么就攤上這事∶溏郑” “怎么了灸撰?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拼坎。 經常有香客問我浮毯,道長,這世上最難降的妖魔是什么泰鸡? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任债蓝,我火速辦了婚禮,結果婚禮上盛龄,老公的妹妹穿的比我還像新娘惦蚊。我一直安慰自己器虾,他們只是感情好讯嫂,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布蹦锋。 她就那樣靜靜地躺著,像睡著了一般欧芽。 火紅的嫁衣襯著肌膚如雪莉掂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天千扔,我揣著相機與錄音憎妙,去河邊找鬼。 笑死曲楚,一個胖子當著我的面吹牛厘唾,可吹牛的內容都是我干的。 我是一名探鬼主播龙誊,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼抚垃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了趟大?” 一聲冷哼從身側響起鹤树,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逊朽,沒想到半個月后罕伯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡叽讳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年追他,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片岛蚤。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡邑狸,死狀恐怖,靈堂內的尸體忽然破棺而出灭美,到底是詐尸還是另有隱情推溃,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布届腐,位于F島的核電站铁坎,受9級特大地震影響,放射性物質發(fā)生泄漏犁苏。R本人自食惡果不足惜硬萍,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望围详。 院中可真熱鬧朴乖,春花似錦祖屏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至畜普,卻和暖如春期丰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吃挑。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工钝荡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人舶衬。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓埠通,卻偏偏與公主長得像,于是被迫代替她去往敵國和親逛犹。 傳聞我的和親對象是個殘疾皇子端辱,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內容