java設計模式學習筆記15-命令模式

 

命令模式command屬於對象的行爲模式,又稱爲行動action模式或交易tracscation模式;

命令模式把一個請求或操作封裝到一個對象中,允許系統使用不同的請求把客戶端參數化,對請求排隊或記錄日誌,可以提供命令的撤銷和恢復功能;

1. 接收者角色

/**
 * 命令模式-接收者角色 
 */
@Slf4j
public class DeskReceiver {

    public void createDeskLeg() {
        log.info("命令模式-接收者角色---製造桌腿");
    }

    public void createDeskTop() {
        log.info("命令模式-接收者角色---製造桌面");
    }

    public void installDesk() {
        log.info("命令模式-接收者角色---組裝零件");
    }

    public void checkDesk() {
        log.info("命令模式-接收者角色---檢測桌子");
    }
}

2. 命令角色

/**
 * 命令模式-抽象命令角色 
 */
public interface DeskCommand {

    /**
     * 執行方法
     */
    void execute();
}

3. 具體命令角色

/**
 * 命令模式-具體命令角色-桌腿製造 
 */
@Slf4j
public class DeskLegConcreteCommand implements DeskCommand {

    private DeskReceiver receiver;

    public DeskLegConcreteCommand(DeskReceiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        log.info("命令模式-具體命令角色(桌腿生產者)-調用接收者-去製造桌腿");
        receiver.createDeskLeg();
    }
}
/**
 * 命令模式-具體命令角色-桌面製造 
 */
@Slf4j
public class DeskTopConcreteCommand implements DeskCommand {

    private DeskReceiver receiver;

    public DeskTopConcreteCommand(DeskReceiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        log.info("命令模式-具體命令角色(桌面生產者)-調用接收者-去製造桌面");
        receiver.createDeskTop();
    }
}
/**
 * 命令模式-具體命令角色-零件組裝 
 */
@Slf4j
public class DeskInstallConcreteCommand implements DeskCommand {

    private DeskReceiver receiver;

    public DeskInstallConcreteCommand(DeskReceiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        log.info("命令模式-具體命令角色(組裝者)-調用接收者-去組裝零件");
        receiver.installDesk();
    }
}
/**
 * 命令模式-具體命令角色-檢測質量 
 */
@Slf4j
public class DeskCheckConcreteCommand implements DeskCommand {

    private DeskReceiver receiver;

    public DeskCheckConcreteCommand(DeskReceiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        log.info("命令模式-具體命令角色(檢測者)-調用接收者-去檢測質量");
        receiver.checkDesk();
    }
}

4. 請求者角色

/**
 * 命令模式-請求者角色-桌子工廠的老闆 
 */
public class DeskInvoker {
    /**
     * 持有具體命令角色
     */
    private DeskCommand deskLegConcreteCommand;
    private DeskCommand deskTopConcreteCommand;
    private DeskCommand deskInstallConcreteCommand;
    private DeskCommand deskCheckConcreteCommand;

    public DeskInvoker(DeskCommand deskLegConcreteCommand, DeskCommand deskTopConcreteCommand,
                       DeskCommand deskInstallConcreteCommand, DeskCommand deskCheckConcreteCommand) {
        this.deskLegConcreteCommand = deskLegConcreteCommand;
        this.deskTopConcreteCommand = deskTopConcreteCommand;
        this.deskInstallConcreteCommand = deskInstallConcreteCommand;
        this.deskCheckConcreteCommand = deskCheckConcreteCommand;
    }

    public void createDeskLeg() {
        deskLegConcreteCommand.execute();
    }

    public void createDeskTop() {
        deskTopConcreteCommand.execute();
    }

    public void installDesk() {
        deskInstallConcreteCommand.execute();
    }

    public void checkDesk() {
        deskCheckConcreteCommand.execute();
    }
}

5. 客戶端角色-測試

/**
 * 命令模式-客戶端角色-桌子購買者 
 */
@Slf4j
public class DeskClient {

    @Test
    public void test() {
        DeskReceiver receiver = new DeskReceiver();
        log.info("創建接收者角色======");

        DeskCommand deskLegConcreteCommand = new DeskLegConcreteCommand(receiver);
        DeskCommand deskTopConcreteCommand = new DeskTopConcreteCommand(receiver);
        DeskCommand deskInstallConcreteCommand = new DeskInstallConcreteCommand(receiver);
        DeskCommand deskCheckConcreteCommand = new DeskCheckConcreteCommand(receiver);
        log.info("創建具體命令角色-同時設定接收者======");

        DeskInvoker invoker = new DeskInvoker(deskLegConcreteCommand, deskTopConcreteCommand,
                deskInstallConcreteCommand, deskCheckConcreteCommand);
        log.info("創建請求者角色-同時設定具體命令者======");

        invoker.createDeskLeg();
        invoker.createDeskTop();
        invoker.installDesk();
        invoker.checkDesk();
    }
}

6. 測試結果

7. 宏命令就是多個命令的組合

7.1 宏命令接口

/**
 * 命令模式-宏命令-接口 - 繼承抽象命令角色
 */
public interface MacroDesk extends DeskCommand {
    /**
     * 宏命令聚集的管理方法-新增成員命令
     *
     * @param command 待新增的具體命令角色
     */
    void add(DeskCommand command);

    /**
     * 宏命令聚集的管理方法-刪除成員命令
     *
     * @param command 待刪除的具體命令角色
     */
    void remove(DeskCommand command);
}

7.2 宏命令實現類

/**
 * 命令模式-宏命令-實現類 
 */
public class MacroDeskCreator implements MacroDesk {

    private List<DeskCommand> commandList = new ArrayList<>();

    @Override
    public void add(DeskCommand command) {
        commandList.add(command);
    }

    @Override
    public void remove(DeskCommand command) {
        commandList.remove(command);
    }

    @Override
    public void execute() {
        for (DeskCommand command : commandList) {
            command.execute();
        }
    }
}

7.3 宏命令測試

/**
 * 命令模式-宏命令-測試 
 */
@Slf4j
public class MacroDeskTest {

    @Test
    public void test() {
        DeskReceiver receiver = new DeskReceiver();
        log.info("創建接收者角色======");

        DeskCommand deskLegConcreteCommand = new DeskLegConcreteCommand(receiver);
        DeskCommand deskTopConcreteCommand = new DeskTopConcreteCommand(receiver);
        DeskCommand deskInstallConcreteCommand = new DeskInstallConcreteCommand(receiver);
        DeskCommand deskCheckConcreteCommand = new DeskCheckConcreteCommand(receiver);
        log.info("創建具體命令角色-同時設定接收者======");

        MacroDesk macroDesk = new MacroDeskCreator();
        macroDesk.add(deskLegConcreteCommand);
        macroDesk.add(deskTopConcreteCommand);
        macroDesk.add(deskInstallConcreteCommand);
        macroDesk.add(deskCheckConcreteCommand);
        log.info("宏命令-加入具體命令者======");

        macroDesk.execute();

        macroDesk.remove(deskTopConcreteCommand);
        log.info("宏命令-刪除一個具體命令者======");

        macroDesk.execute();
    }
}

7.4 測試結果:

命令模式實現了命令發起者即客戶端角色與具體命令角色的完全解耦,易於擴展新的功能,不需要改變已有的實現;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章