• 命令模式


    命令模式

    命令模式Command Pattern是一种数据驱动的设计模式,其属于行为型模式,别名为动作Action模式或事务Transaction模式,命令模式将请求以命令的形式包裹在对象中,并传给调用对象,调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象对请求排队或者记录请求日志,以及支持可撤销的操作。

    描述

    在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活。命令模式可以对发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。命令模式也可以用于实现基于事务的系统,一旦执行命令,便会继续保留命令的历史记录,如果最终命令成功执行,那么一切都很好,否则只需遍历历史记录并继续对所有已执行的命令执行撤消即可。

    优点

    • 降低系统的耦合度。
    • 新的命令可以很容易地加入到系统中。
    • 可以比较容易地设计一个命令队列和宏命令(组合命令)。
    • 可以方便地实现对请求的Undo和Redo。

    缺点

    • 使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

    适用环境

    • 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
    • 系统需要在不同的时间指定请求、将请求排队和执行请求。
    • 系统需要支持命令的撤销Undo操作和恢复Redo操作。
    • 系统需要将一组操作组合在一起,即支持宏命令

    实现

    // 假设我们有一个电灯,我们使用遥控器对其进行控制
    
    class Bulb {
        turnOn() {
            console.log("Bulb has been lit!");
        }
        
        turnOff() {
            console.log("Darkness!");
        }
    }
    
    class Command {
        execute(){
            throw new Error("Abstract method cannot be called");
        }
    
        redo(){
            throw new Error("Abstract method cannot be called");
        }
    
        undo(){
            throw new Error("Abstract method cannot be called");
        }
    }
    
    class TurnOnCommand extends Command{
        constructor(bulb) {
            super();
            this.bulb = bulb;
        }
        
        execute() {
            this.bulb.turnOn();
        }
        
        undo() {
            this.bulb.turnOff();
        }
        
        redo() {
            this.execute();
        }
    }
    
    class TurnOffCommand extends Command {
        constructor(bulb) {
            super();
            this.bulb = bulb;
        }
        
        execute() {
            this.bulb.turnOff();
        }
        
        undo() {
            this.bulb.turnOn();
        }
        
        redo() {
            this.execute();
        }
    }
    
    class RemoteControl {
        submit(command) {
            command.execute();
        }
    }
    
    (function(){
        var bulb = new Bulb();
    
        var turnOn = new TurnOnCommand(bulb);
        var turnOff = new TurnOffCommand(bulb);
    
        var remote = new RemoteControl();
        remote.submit(turnOn); // Bulb has been lit!
        remote.submit(turnOff); // Darkness!
    })();
    

    每日一题

    https://github.com/WindrunnerMax/EveryDay
    

    参考

    https://www.runoob.com/design-pattern/command-pattern.html
    https://github.com/sohamkamani/javascript-design-patterns-for-humans#-command
    https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/command.html
    
  • 相关阅读:
    无向图判断割点
    C
    连通图 求至少有给几个点信息才能传遍全图,至少添加几条边才能使全图联通
    线段树区间更新(set暴力)
    A
    辗转相除法(数学推理)
    Python List index()方法
    Python List extend()方法
    Python List count()方法
    Python List append()方法
  • 原文地址:https://www.cnblogs.com/WindrunnerMax/p/13897236.html
Copyright © 2020-2023  润新知