設(shè)計模式解密(11)- 命令模式

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

◆ 前言:命令模式內(nèi)容比較多,這里做了拆分

命令模式基礎(chǔ)篇 :http://www.cnblogs.com/JsonShare/p/7202133.html

命令模式擴(kuò)展篇 - 宏命令:http://www.cnblogs.com/JsonShare/p/7206395.html

命令模式擴(kuò)展篇 - 撤銷命令:http://www.cnblogs.com/JsonShare/p/7206513.html

命令模式擴(kuò)展篇 - 命令隊列:http://www.cnblogs.com/JsonShare/p/7206607.html

命令模式擴(kuò)展篇 - 請求日志:http://www.cnblogs.com/JsonShare/p/7206665.html

1、簡介

定義:將一個請求封裝為一個對象,從而使你可以用不同的請求對客戶進(jìn)行參數(shù)化,對請求排隊和記錄請求日志,以及支持可撤銷的操作;

主要解決:在軟件系統(tǒng)中,行為請求者與行為實現(xiàn)者通常是一種緊耦合的關(guān)系,但某些場合,比如需要對行為進(jìn)行記錄、撤銷或重做、事務(wù)等處理時,這種緊耦合的設(shè)計就不太合適;

英文:Command

類型:行為型模式

2、類圖及組成

(引)類圖:

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

組成:
  ● Command(抽象命令類):抽象命令類一般是一個抽象類或接口,在其中聲明了用于執(zhí)行請求的execute()等方法,通過這些方法可以調(diào)用請求接收者的相關(guān)操作。

  ● ConcreteCommand(具體命令類):具體命令類是抽象命令類的子類,實現(xiàn)了在抽象命令類中聲明的方法,它對應(yīng)具體的接收者對象,將接收者對象的動作綁定其中。在實現(xiàn)execute()方法時,將調(diào)用接收者對象的相關(guān)操作(Action)。

  ● Invoker(調(diào)用者):調(diào)用者即請求發(fā)送者,它通過命令對象來執(zhí)行請求。一個調(diào)用者并不需要在設(shè)計時確定其接收者,因此它只與抽象命令類之間存在關(guān)聯(lián)關(guān)系。在程序運行時可以將一個具體命令對象注入其中,再調(diào)用具體命令對象的execute()方法,從而實現(xiàn)間接調(diào)用請求接收者的相關(guān)操作。

  ● Receiver(接收者):接收者請求與執(zhí)行相關(guān)的操作,它具體實現(xiàn)對請求的業(yè)務(wù)處理。

  ● Client(客戶端角色類):最終的客戶端調(diào)用類。

代碼結(jié)構(gòu):

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

抽象命令角色類public interface Command {    /**
     * 執(zhí)行方法     */
    void execute();
}

具體命令角色類public class ConcreteCommand implements Command {    //持有相應(yīng)的接收者對象
    private Receiver receiver = null;    /**
     * 構(gòu)造方法     */
    public ConcreteCommand(Receiver receiver){        this.receiver = receiver;
    }
    @Override    public void execute() {        //通常會轉(zhuǎn)調(diào)接收者對象的相應(yīng)方法,讓接收者來真正執(zhí)行功能        receiver.action();
    }
}

接收者角色類public class Receiver {    /**
     * 真正執(zhí)行命令相應(yīng)的操作     */
    public void action(){
        System.out.println("執(zhí)行操作");
    }
}

請求者角色類public class Invoker {    /**
     * 持有命令對象     */
    private Command command = null;    /**
     * 構(gòu)造方法     */
    public Invoker(Command command){        this.command = command;
    }    /**
     * 行動方法     */
    public void action(){
        command.execute();
    }
}

客戶端角色類public class Client {    public static void main(String[] args) {        //創(chuàng)建接收者
        Receiver receiver = new Receiver();        //創(chuàng)建命令對象,設(shè)定它的接收者
        Command command = new ConcreteCommand(receiver);        //創(chuàng)建請求者,把命令對象設(shè)置進(jìn)去
        Invoker invoker = new Invoker(command);        //執(zhí)行方法        invoker.action();
    }
}

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

3、實例引入

下面以電視機(jī)的開、關(guān)命令為例,進(jìn)行講解:

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

package com.designpattern.Command;/**
 * 抽象命令角色類
 * @author Json*/public interface Command {     /**
     * 執(zhí)行方法     */
    void execute();
}

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

package com.designpattern.Command;/**
 * 接收者角色類  -- 電視
 * @author Json*/public class TV {    /**
     * 打開方法     */
    public void on(){
        System.out.println("電視打開");
    }    /**
     * 關(guān)閉方法     */
    public void off(){
        System.out.println("電視關(guān)閉");
    }
}

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

package com.designpattern.Command;/**
 * 具體命令角色類  -- 電視打開命令
 * @author Json*/public class TVOnCommand implements Command {    private TV tv;    public TVOnCommand(TV tv){        this.tv = tv;
    }
    
    @Override    public void execute() {
        tv.on();
    }
}

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

package com.designpattern.Command;/**
 * 具體命令角色類  -- 電視關(guān)閉命令
 * @author Json*/public class TVOffCommand implements Command {    private TV tv;    public TVOffCommand(TV tv){        this.tv = tv;
    }
    
    @Override    public void execute() {
        tv.off();
    }
}

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

package com.designpattern.Command;/**
 * 請求者角色類  -- 遙控器Invoker
 * @author Json*/public class RemoteControl {    private Command onCommand,offCommand;    
    public RemoteControl(Command _on,Command _off){        this.onCommand = _on;        this.offCommand = _off;
    }    
    public void turnOn(){
        onCommand.execute();
    }    
    public void turnOff(){
        offCommand.execute();
    }
}

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

 測試:

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

package com.designpattern.Command;/**
 * 客戶端角色類
 * @author Json*/public class Client {    public static void main(String[] args) {        //創(chuàng)建接收者
        TV receiver = new TV();        //創(chuàng)建命令對象,設(shè)定它的接收者
        Command on_command = new TVOnCommand(receiver);        //創(chuàng)建命令對象,設(shè)定它的接收者
        Command off_command = new TVOffCommand(receiver);        //命令控制對象Invoker,把命令對象通過構(gòu)造方法設(shè)置進(jìn)去 或者 增加set方法set進(jìn)去是一樣的(setCommand方法未寫)
        RemoteControl invoker = new RemoteControl(on_command,off_command);        //執(zhí)行方法  -- 打開電視        invoker.turnOn();        //執(zhí)行方法 -- 關(guān)閉電視        invoker.turnOff();
    }
}

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

 結(jié)果:

電視打開
電視關(guān)閉

關(guān)于例子的補(bǔ)充說明:

雖然代碼看似挺多,但其實命令模式的結(jié)構(gòu)還是比較清晰的,總的來說命令模式的使用流程就是首先創(chuàng)建一個抽象命令,然后創(chuàng)建多個具體命令實現(xiàn)抽象命令接口,然后創(chuàng)建一個命令接受者角色,它包含各種的行為的具體實現(xiàn),然后再有一個命令調(diào)用者角色,提供給客戶端,用于接收客戶端的參數(shù);

4、命令模式的擴(kuò)展

 由于篇幅太長,這里單獨拆分出去了;

傳送門:

  命令模式擴(kuò)展篇 - 宏命令:http://www.cnblogs.com/JsonShare/p/7206395.html

  命令模式擴(kuò)展篇 - 撤銷命令:http://www.cnblogs.com/JsonShare/p/7206513.html

  命令模式擴(kuò)展篇 - 命令隊列:http://www.cnblogs.com/JsonShare/p/7206607.html

  命令模式擴(kuò)展篇 - 請求日志:http://www.cnblogs.com/JsonShare/p/7206665.html

5、優(yōu)缺點

優(yōu)點:

  1、命令模式將行為調(diào)用者和各種行為分隔開,降低程序的耦合,便于程序擴(kuò)展;

  2、命令模式將行為的具體實現(xiàn)封裝起來,客戶端無需關(guān)心行為的具體實現(xiàn);

  3、命令模式可為多種行為提供統(tǒng)一的調(diào)用入口,便于程序?qū)π袨榈墓芾砗涂刂疲?/p>

缺點:

  使用命令模式的話,不用管命令多簡單,都需要寫一個命令類來封裝,使用命令模式可能會導(dǎo)致系統(tǒng)有過多的具體命令類;

     (上面的例子就可以看出,每個命令都要有一個具體的命令類);

6、應(yīng)用場景

  1、希望將行為請求者和行為實現(xiàn)者解耦,不直接打交道;

  2、希望分離掉行為請求者一部分的責(zé)任,行為請求者只需要將命令發(fā)給調(diào)用者,不再主動的去讓行為實現(xiàn)者產(chǎn)生行為,符合單一職責(zé)原則;

  3、希望可以控制執(zhí)行的命令列表,方便記錄,撤銷/重做以及事務(wù)等功能;

  4、期待可以將請求排隊,有序執(zhí)行;

  5、希望可以將請求組合使用,即支持宏命令;

7、總結(jié)

  命令模式最大的好處就是實現(xiàn)了行為請求者與行為實現(xiàn)者的解耦;

  在實際場景中的使用:

      Struts2中action中的調(diào)用過程中存在命令模式;

      數(shù)據(jù)庫中的事務(wù)機(jī)制的底層實現(xiàn);

      命令的撤銷和恢復(fù):增加相應(yīng)的撤銷和恢復(fù)命令的方法(比如數(shù)據(jù)庫中的事務(wù)回滾);

  例如:Java的Runnable就是命令模式的變形應(yīng)用:

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

public class Test {    public static void main(String[] args) {        //范例
        Runnable runnable = () -> System.out.println("具體命令"); // Command cmd = ConcreteCommand
        Thread thread1 = new Thread(runnable); // 將 cmd 交給 Thread (Invoker)
        thread1.start(); // Invoker 調(diào)用 cmd 的執(zhí)行方法    }
}

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

 

 

PS:源碼地址   https://github.com/JsonShare/DesignPattern/tree/master 

     

如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力! 
如果標(biāo)題被標(biāo)記為轉(zhuǎn)載,轉(zhuǎn)載請注明原作者地址,詳見引用 
版權(quán)聲明,轉(zhuǎn)載請注明出處:http://www.cnblogs.com/JsonShare

http://www.cnblogs.com/JsonShare/p/7202133.html