• Go和Java实现命令模式


    Go和Java实现命令模式

    下面通过一个烧烤的例子来说明命令模式的使用。

    1、命令模式

    命令模式是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调

    用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

    • 意图:将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化,对请求排队或记录请求日

      志,以及支持可撤消的操作。

    • 主要解决:在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为

      进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

    • 何时使用:在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是

      不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者

      之间的松耦合。

    • 如何解决:通过调用者调用接受者执行命令,顺序:调用者→命令→接受者。

    • 关键代码:定义三个角色:1、received 真正的命令执行对象 2、Command 3、invoker 使用命令对象的入口

    • 应用实例:struts 1 中的 action 核心控制器 ActionServlet 只有一个,相当于 Invoker,而模型层的类会随着

      不同的应用有不同的模型类,相当于具体的 Command。

    • 优点:1、降低了系统耦合度。 2、新的命令可以很容易添加到系统中去。

    • 缺点:使用命令模式可能会导致某些系统有过多的具体命令类。

    • 使用场景:认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟

      CMD。

    • 注意事项:系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,也可以考虑使用命令模式。

    • 适用性:

      抽象出待执行的动作以参数化某对象。

      在不同的时刻指定、排列和执行请求。

      支持取消操作。

      支持修改日志,这样当系统崩溃时,这样修改可以被重做一遍。

      用构建在原语操作上的高层操作构造一个系统。

    2、Go实现命令模式

    package command
    
    // ========== 声明执行操作的接口 ==========
    // ========== Command ==========
    type Command interface {
    	// 执行命令
    	executeCommand()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    package command
    
    // ========== 将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute ==========
    // ========== BakeChickWingCommand烤鸡翅命令 ==========
    type BakeChickWingCommand struct {
    	Barbecuer
    }
    
    func (bakeChickWingCommand *BakeChickWingCommand) executeCommand() {
    	bakeChickWingCommand.Barbecuer.bakeChickWing()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    package command
    
    // ========== 将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute ==========
    // ========== BakeMuttonCommand烤羊肉串命令 ==========
    type BakeMuttonCommand struct {
    	Barbecuer
    }
    
    func (bakeMuttonCommand *BakeMuttonCommand) executeCommand() {
    	bakeMuttonCommand.Barbecuer.bakeMutton()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    package command
    
    import "fmt"
    
    // 知道如何实现与执行一个请求相关的操作,任何类都可能作为一个接收者
    // ========== Barbecuer烧烤串者 ==========
    type Barbecuer struct{}
    
    // 考羊肉串
    func (barbecuer *Barbecuer) bakeMutton() {
    	fmt.Println("考羊肉串!")
    }
    
    // 考鸡翅
    func (barbecuer *Barbecuer) bakeChickWing() {
    	fmt.Println("考鸡翅!")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    package command
    
    // 要求该命令执行这个请求
    // ========== 服务员Waiter ==========
    type Waiter struct {
    	Command
    }
    
    func (waiter *Waiter) SetOrder(command Command) {
    	waiter.Command = command
    }
    
    // 通知执行
    func (waiter *Waiter) Execute() {
    	waiter.Command.executeCommand()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    package main
    
    import . "proj/command"
    
    func main() {
    	// 开店前的准备
    	// 烧烤师傅
    	barbecuer := Barbecuer{}
    	// 烧烤菜单
    	bakeMuttonCommand := BakeMuttonCommand{Barbecuer: barbecuer}
    	bakeChickWingCommand := BakeChickWingCommand{Barbecuer: barbecuer}
    	// 服务员
    	waiter := Waiter{}
    	// 开门营业
    	// 根据用户需要通知厨房
    	waiter.SetOrder(&bakeMuttonCommand)
    	// 开始制作
    	waiter.Execute()
    	waiter.SetOrder(&bakeChickWingCommand)
    	waiter.Execute()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    # 程序输出
    考羊肉串!
    考鸡翅!
    
    • 1
    • 2
    • 3

    3、Java实现命令模式

    package com.command;
    
    // ========== 声明执行操作的接口 ==========
    // ========== Command ==========
    public abstract class Command {
        protected Barbecuer receive;
    
        public Command(Barbecuer receive) {
            this.receive = receive;
        }
    
        // 执行命令
        public abstract void executeCommand();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    package com.command;
    
    // ========== 将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute ==========
    // ========== BakeChickWingCommand烤鸡翅命令 ==========
    public class BakeChickWingCommand extends Command {
        
        public BakeChickWingCommand(Barbecuer receive) {
            super(receive);
        }
    
        @Override
        public void executeCommand() {
            this.receive.bakeChickWing();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    package com.command;
    
    // ========== 将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute ==========
    // ========== BakeMuttonCommand烤羊肉串命令 ==========
    public class BakeMuttonCommand extends Command {
    
        public BakeMuttonCommand(Barbecuer receive) {
            super(receive);
        }
    
        @Override
        public void executeCommand() {
            this.receive.bakeMutton();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    package com.command;
    
    // 知道如何实现与执行一个请求相关的操作,任何类都可能作为一个接收者
    // ========== Barbecuer烧烤串者 ==========
    public class Barbecuer {
    
        // 考羊肉串
        public void bakeMutton(){
            System.out.println("考羊肉串!");
        }
    
        // 考鸡翅
        public void bakeChickWing(){
            System.out.println("考鸡翅!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    package com.command;
    
    // 要求该命令执行这个请求
    // ========== 服务员Waiter ==========
    public class Waiter {
        private Command command;
    
        public void setOrder(Command command) {
            this.command = command;
        }
    
        // 通知执行
        public void execute() {
            this.command.executeCommand();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    package com.command;
    
    public class Test {
        public static void main(String[] args) {
            // 开店前的准备
            // 烧烤师傅
            Barbecuer barbecuer = new Barbecuer();
            // 烧烤菜单
            Command bakeMuttonCommand = new BakeMuttonCommand(barbecuer);
            Command bakeChickWingCommand = new BakeChickWingCommand(barbecuer);
            // 服务员
            Waiter waiter = new Waiter();
            // 开门营业
            // 根据用户需要通知厨房
            waiter.setOrder(bakeMuttonCommand);
            // 开始制作
            waiter.execute();
            waiter.setOrder(bakeChickWingCommand);
            waiter.execute();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    # 程序输出
    考羊肉串!
    考鸡翅!
    
    • 1
    • 2
    • 3
  • 相关阅读:
    如何找到并快速上手一个开源项目
    【Luogu】 P5642 人造情感(emotion)
    HDL-Bits 刷题记录 03
    python中函数的参数
    alist配合onlyoffice 实现在线预览
    设计模式之适配器模式
    用于标记蛋白质和抗体的Biotin-LC-Sulfo-NHS|CAS:191671-46-2
    微信CRM系统:企业管理的黄金工具!
    STM32使用HAL库驱动DS3231
    WPF动画(2)
  • 原文地址:https://blog.csdn.net/qq_30614345/article/details/130475225