Command命令模式(行为型模式)

目录

动机(Motivation)

意图(Intent)

结构(Structure)

Command模式的几个要点

Exampel


动机(Motivation)

在软件构建过程中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合--比如需要对行为进行“记录、撤销/重做(undo/redo)、事务”等处理,这种无法抵御变化的紧耦合是不合适的。

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

意图(Intent)

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对其排队或者记录请求日志,支持可撤销的操作。

结构(Structure)

Command:定义命令的接口,声明执行的方法。

ConcreteCommand:命令接口实现对象,是“虚”的实现,通常会有接受者,并调用接受者的功能来完成命令要执行的操作。

Receiver:接受者,真正执行命令的对象。任何类都可能成为一个接受者,只要它能够实现命令要求实现的相应功能。

Invoker:要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。

Client:创建具体的命令对象,并且设置命令对象的接受者。这不是常规意义上的客户端,而是在组装命令对象和接受者,真正使用命令的客户端是从Invoker来触发执行。

Command模式的几个要点

1.Command模式的根本目的在于将“行为请求者”与“行为实现者”解耦,在面向对象语言中,常见的实现手段是“将行为抽象为对象”。

2.实现Command接口的具体命令对象ConcereteCommand有时候根据需要可能会保存一些额外的状态信息。

Exampel

背景:街边的烧烤摊很多都是一个人边做边卖,把消费者看做是命令的请求者(发出购买烤串的命令),烤串的人看作是命令的接受者(接收购买烤串命令进行烧烤),这就是一个紧耦合的关系。

而一般正规的烧烤店,都是由服务员负责顾客的点餐,顾客点餐之后,服务员会通知后厨进行制作。(这就将命令的请求者和命令的接受者解耦)。

下面是具体的代码实现

烤肉串者:对应于结构图中的Receiver类,也就是命令请求的实际执行者。在本例中,就是后厨的大厨们,为我们烤美味的羊肉串和鸡翅。

     public class Barbecuer
    {
        //烤羊肉
        public void BakeMutton()
        {
            Console.WriteLine("烤羊肉串!");
        }
        //烤鸡翅...
    }

抽象命令类:对应于结构图中的Command,定义命令的接口,声明执行的方法。在本例中,抽象命令类,只需要确定“烤肉串者”是谁,而不需要知道Barbecuer里面的具体行为(方法)。

    public abstract class Command
    {
        protected Barbecuer receiver;
        //抽象命令类,只需要确定“烤肉串者”是谁
        public Command(Barbecuer receiver)
        {
            this.receiver = receiver;
        }
        //执行命令
        abstract public void ExecuteCommand();
    }

烤羊肉串命令和烤鸡翅命令类:对应于结构图中的ConcreteCommand,实现Command的命令接口,并且执行receiver的具体的行为。在本例中,具体命令类中要执行大厨的具体行为(烤羊肉串,烤鸡翅)。

     //烤羊肉串命令
    class BakeMuttonCommand : Command
    {
        public BakeMuttonCommand(Barbecuer receiver) : base(receiver) { }
        //具体命令类,执行命令时,执行具体的行为
        public override void ExecuteCommand()
        {
            receiver.BakeMutton();
        }
    }
    //烤鸡翅命令类
    class BakeChickenWingCommand : Command
    {
        //代码同上
    }

服务员类:对应于结构图中的Invoker类,触发命令对象的执行。在本例中,服务员给后厨要求后厨按订单制作,并且记录顾客对订单的增加和撤销情况,以备结账使用。

public class Waiter
    {
        //存放具体命令的容器
        private IList<Command> orders = new List<Command>();
        //设置订单
        public void SetOrder(Command command)
        {
            //在客户提出请求时,对没货的烧烤进行回绝
            if (command.ToString()=="实例.BakeChickenWingCommand")
            {
                Console.WriteLine("服务员:鸡翅没有了,请点别的烧烤");
            }
            else
            {
                orders.Add(command);
                //记录客户所点的烧烤的日志,以备算账收钱
                Console.WriteLine("增加订单:"+command.ToString()+"时间:"+DateTime.Now.ToString());
            }
        }
        //取消订单
        public void CancelOrder(Command command)
        {
            orders.Remove(command);
            Console.WriteLine("取消订单:"+command.ToString()+"时间:"+DateTime.Now.ToString());
        }
        //通知执行
        public void Notify()
        {
            //根据用户点好的烧烤订单通知厨房制作
            foreach (Command cmd in orders)
            {
                cmd.ExecuteCommand();
            }
        }
    }

客户端代码:创建具体的命令对象,并且设置命令对象的接受者。在本例中,在开店前设置了命令对象和命令对象的接受者Barbecuer。

            //开店前准备
            Barbecuer boy = new Barbecuer();
            Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);
            Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);
            Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);
            Waiter girl = new Waiter();
            //开门营业,顾客点菜
            girl.SetOrder(bakeMuttonCommand1);
            girl.SetOrder(bakeMuttonCommand2);
            girl.SetOrder(bakeChickenWingCommand1);
            //点菜完毕,通知厨房
            girl.Notify();

如有问题,欢迎指正~~~~

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
命令模式是一种行为设计模式,它将请求封装成一个对象,从而使得请求的发送者和接收者解耦。在命令模式中,请求以命令的形式包裹在对象中,并传递给调用对象。调用对象寻找可以处理该命令的合适的对象,并将命令传递给相应的对象,该对象执行命令。 在C语言中,可以使用函数指针来实现命令模式。具体步骤如下: 1. 定义一个命令接口,该接口包含一个执行命令的方法。 2. 创建具体的命令类,实现命令接口,并在执行方法中调用相应的函数。 3. 创建一个调用者类,该类包含一个命令对象,并提供一个执行命令的方法。 4. 在调用者类中,将命令对象传递给相应的对象,并调用命令对象的执行方法。 下面是一个简单的示例代码: ```c #include <stdio.h> // 定义命令接口 typedef struct { void (*execute)(void); } Command; // 创建具体的命令类 typedef struct { Command command; void (*function)(void); } ConcreteCommand; void concreteCommand_execute(void) { printf("执行具体的命令\n"); } // 创建调用者类 typedef struct { Command *command; void (*setCommand)(Command *command); void (*executeCommand)(void); } Invoker; void invoker_setCommand(Command *command) { Invoker *invoker = (Invoker *)command; invoker->command = command;} void invoker_executeCommand(void) { Invoker *invoker = (Invoker *)invoker->command; invoker->command->execute(); } int main() { // 创建具体的命令对象 ConcreteCommand concreteCommand; concreteCommand.command.execute = concreteCommand_execute; concreteCommand.function = concreteCommand_execute; // 创建调用者对象 Invoker invoker; invoker.setCommand((Command *)&concreteCommand); invoker.executeCommand(); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值