設計模式之命令模式

       操做數據庫時有各類操做,即有插入,刪除,又有更新。各類操做間,其實能夠當作咱們給數據庫發送命令,讓它根據咱們的命令執行相應的操做。操做模式中的命令模式剛好能夠很好的封裝命令。咱們並不須要數據庫作了什麼具體的操做,咱們須要的就是發出一個命令,以後數據庫按照咱們的命令作相應的操做。java

1、定義

定義(來源:維基百科)Command pattern)是一種設計模式,它嘗試以命令來表明實際操做。命令類能夠把行動(action) 及其參數封裝起來,因而這些行動能夠被:重複屢次、取消後又重作數據庫

看了百度百科的定義,感受不是太好理解,因而我把維基百科的定義從新修飾了一下。設計模式

要點解析:bash

一、經過命令來表示實際的操做。咱們平時寫代碼基本就是須要什麼功能,則直接調用某方法,而命令模式是經過發送一個命令的方式。markdown

二、命令在執行前是能夠被取消、或者重複執行同一個命令的。ide

看了定義可能你還雲裏霧裏的,不是特別清楚命令模式是怎麼回事?別急,你如今只要清楚:1客戶端經過發送命令來作具體的操做。二、操做執行前是能夠取消掉的。this

2、UML

先來看看命令模式下,都涉及到哪些角色:spa

一、首先必須有命令類,因而咱們須要一個命令的抽象類、以下圖中的Command類。設計

二、其次,須要有具體的命令類,你究竟是請求刪數據呢,仍是新增數據呢?你得定義刪除,新增的命令,以下圖中的InsertCommand、DeleteCommand、UpdateCommand。code

三、須要有個類來接收客戶端發送過來的命令,管理這些命令,由於這些命令還須要能夠撤銷。下圖中的Invoke。

四、發送命令過來的本質仍是執行命令表明的具體邏輯,因此還須要有個地方實現這些邏輯,這個角色以下圖的Receiver類,實現具體邏輯



3、代碼實現

接下來看看數據庫操做場景下,命令模式的實現例子

(一)、定義命令的抽象類

package com.design.command;

public abstract class Command {
    //持有具體邏輯操做的引用
    protected Receiver receiver;

    public Command(Receiver receiver) {
        this.receiver = receiver;
    }
    //執行命令的具體邏輯
    public abstract void execute();
}複製代碼

(二)、具體的命令

package com.design.command;

/**
 * 插入命令
 */
public class InsertCommand extends Command {
    //要插入到數據庫的數據
    private String dat;
    public InsertCommand(Receiver receiver) {
        super(receiver);
    }
    //執行插入操做
    @Override
    public void execute() {
        receiver.insertData(dat);
    }

    public String getDat() {
        return dat;
    }

    public void setDat(String dat) {
        this.dat = dat;
    }
}複製代碼

package com.design.command;

/**
 * 刪除命令
 */
public class DeleteCommand extends Command {
    //要刪除數據庫的數據
    private String dat;

    public DeleteCommand(Receiver receiver) {
        super(receiver);
    }

    @Override
    public void execute() {
        super.receiver.deleteData(dat);
    }

    public String getDat() {
        return dat;
    }

    public void setDat(String dat) {
        this.dat = dat;
    }
}複製代碼

package com.design.command;

/**
 * 更新命令
 */
public class UpdateCommand extends Command {

    private String dat;

    public UpdateCommand(Receiver receiver) {
        super(receiver);
    }

    @Override
    public void execute() {
        receiver.updateData(dat);
    }

    public String getDat() {
        return dat;
    }

    public void setDat(String dat) {
        this.dat = dat;
    }
}
複製代碼

(三)、具體實現功能的類

package com.design.command;

public class Receiver {

    /**
     *實現插入指令的功能
     * @param data
     */
    public void insertData(String data){
        System.out.println("插入數據庫數據:"+data);
    };

    /**
     *實現刪除指令的功能
     * @param data
     */
    public void deleteData(String data){
        System.out.println("刪除數據庫數據:"+data);
    };

    /**
     *實現更新指令的功能
     * @param data
     */
    public void updateData(String data){
        System.out.println("更新數據庫數據:"+data);
    };
}複製代碼

(四)、Invoke類,對接客戶端,接收客戶端發來的命令

package com.design.command;

import java.util.ArrayList;
import java.util.List;

public class Invoker {
    //經過一個ArrayList來存儲客戶端發送過來的命令
    private List<Command> commandList = new ArrayList<>();
    //增長命令
    public void addCommand(Command command){
        this.commandList.add(command);
    }
    //取消命令
    public void cancelCommand(Command command){
        this.commandList.remove(command);
    }
   //通知所有命令
    public void executeAllCommand(){
        for (Command command : commandList){
            command.execute();
        }
        commandList.clear();
    }

}複製代碼

(五)、看看怎麼來調用

package com.design.command;

public class TestMain {

    public static void main(String[] args) {
        Receiver receiver = new Receiver();
        //建立插入指令
        InsertCommand insertCmand = new InsertCommand(receiver);
        insertCmand.setDat("用戶名爲:zhangsan");
        //建立刪除指令
        DeleteCommand delCmand = new DeleteCommand(receiver);
        delCmand.setDat("用戶名爲:lisi");
        //建立更新指令
        UpdateCommand updateCamd = new UpdateCommand(receiver);
        updateCamd.setDat("更新zhangsan用戶名爲王五");

        Invoker invoker = new Invoker();
        //發送插入指令
        invoker.addCommand(insertCmand);
        //發送刪除指令
        invoker.addCommand(delCmand);
        //取消刪除指令
        invoker.cancelCommand(delCmand);
        //發送更新指令
        invoker.addCommand(updateCamd);
        //執行全部指令
        invoker.executeAllCommand();
    }
}
複製代碼

(六)、執行結果


能夠看到,咱們發送了刪除命令,以後咱們作了取消命令的操做,因此最後並無執行取消操做,只執行了插入和更新操做。

4、結論

到此,命令模式的說明還有例子都已經呈現。作個總結:命令模式的做用其實就是將之前直接調用邏輯換成經過發送命令的方法,這個可讓咱們客戶端根具體的邏輯之間進行解耦。其次可輕鬆實現命令的記錄,還有命令的取消、命令的重複等操做。

(一)、優勢

一、如上表述、可解耦客戶端與具體邏輯。

二、可方便對執行的操做進行記錄,如咱們能夠在Invoke類中對執行的命令進行記錄。

三、擴展性好,新增命令簡單,只需新增長具體命令類。

四、可進行命令撤銷,重複執行命令等。

(二)、缺點

一、可能會形成具體的命令類過多。

相關文章
相關標籤/搜索