设计模式-命令模式

设计模式-命令模式

定义:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

使用场景
(1) 需要对方法的请求这和方法的实现者解耦,使得调用者和接收者不直接交互
(2) 需要对操作进行 撤销、恢复、记录
(3) 需要在不同的时间指定请求、将请求排队和执行请求

命令模式类图如下
在这里插入图片描述
Receiver 接收者角色
可以是具体类,也可以是抽象类、接口,执行命令的角色

Command 抽象命令角色
抽象出命令对象,可以根据不同的命令类型,写出不同的实现类

ConcreteCommand 具体命令类
实现了抽象命令类的角色

Invoker 调用者/请求者
请求的发送者,它通过命令对象来执行请求,可以持有若干个命令对象

Client 客户端
在客户端(不是常规意义上的客户端,而是组装命令对象和接受者的类)中需要创建调用者对象,具体命令类对象,在创建具体命令对象时指定对应的接收者,发送者和接收者之间没有关联,可以通过命令对象来调用。

实例:
应该都玩过游戏,我们通过操作游戏界面上的按钮,来控制游戏人物 移动、跳跃、攻击等,玩家每次操作的按钮可以封装为不同的具体命令,游戏人物则是这些命令的接收者。

代码实现如下
Receiver 接收者角色
下面直接定义了具体的接收者,也可以对接收者加一层抽象

    // 游戏人物:接收者
    public class Player
    {
        // 移动
        public void Move(int x, int y)
        {
            string msg = string.Format("向着摇杆_({0}, {1}) 方向移动 \n", x, y);
            Console.WriteLine(msg);
        }

        // 跳跃
        public void Jump()
        {
            Console.WriteLine("跳起 \n");
        }

        // 攻击
        public void Attack()
        {
            Console.WriteLine("攻击 \n");
        }
    }

Command 抽象命令角色

    // 抽象命令
    public interface ICommand
    {
        void OnExecute();
    }

ConcreteCommand 具体命令类

    // 摇杆命令:具体命令
    public class RockerCommand : ICommand
    {
        private Player _player;
        private int _x;
        private int _y;
        public RockerCommand(Player player)
        {
            _player = player;
        }

        public void RockerInfo(int x, int y)
        {
            _x = x;
            _y = y;
        }

        public void OnExecute()
        {
            // 调用移动
            _player.Move(_x, _y);
        }
    }

    // 起跳命令:具体命令
    public class JumpCommand : ICommand
    {
        private Player _player;
        public JumpCommand(Player player)
        {
            _player = player;
        }

        public void OnExecute()
        {
            // 调用跳跃
            _player.Jump();
        }
    }

    // 攻击命令:具体命令
    public class AttackCommand : ICommand
    {
        private Player _player;
        public AttackCommand(Player player)
        {
            _player = player;
        }

        public void OnExecute()
        {
            // 调用攻击
            _player.Attack();
        }
    }

Invoker 调用者/请求者

    class Game
    {
        private RockerCommand _rockerCommand;
        private JumpCommand _jumpCommand;
        private AttackCommand _attackCommand;

        public Game()
        {
        }

        public void SetRockerCommand(RockerCommand command)
        {
            _rockerCommand = command;
        }

        public void SetJumpCommand(JumpCommand command)
        {
            _jumpCommand = command;
        }

        public void SetAttackCommand(AttackCommand command)
        {
            _attackCommand = command;
        }

        public void RockerInfo(int x, int y)
        {
            _rockerCommand.RockerInfo(5, 6);
            // 调用命令
            _rockerCommand.OnExecute();
        }

        public void Jump()
        {
            // 调用命令
            _jumpCommand.OnExecute();
        }

        public void Attack()
        {
            // 调用命令
            _attackCommand.OnExecute();
        }
    }

Client 调用如下

    public class Client
    {
        public Client()
        {
            // 创建接收者
            Player player = new Player();
            // 创建命令
            RockerCommand rockerCommand = new RockerCommand(player);
            // 创建命令
            JumpCommand jumpCommand = new JumpCommand(player);
            // 创建命令
            AttackCommand attackCommand = new AttackCommand(player);

            // 创建调用者
            Game game = new Game();
            // 添加调用者与命令对象的引用
            game.SetRockerCommand(rockerCommand);
            // 添加调用者与命令对象的引用
            game.SetJumpCommand(jumpCommand);
            // 添加调用者与命令对象的引用
            game.SetAttackCommand(attackCommand);

            game.RockerInfo(5, 6);
            game.Jump();
            game.Attack();
        }
    }

测试结果如下
在这里插入图片描述

优点:
(1) 类间解耦,降低了系统耦合度,调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只需调用 Command 抽象类的 execute 方法即可,不需要了解到底是哪个接收者执行。

(2) 可扩展性, Command 的子类可以非常容易地扩展,而调用者 Invoker 和高层次的模块 Client 不产生严重的代码耦合

缺点:
(1) 使用命令模式可能导致某些系统有过多的具体命名类。因为每一个命令都需要设计一个具体命令类。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值