1命令模式简介

Game Programming Patterns一书中介绍了常用设计模式

命令模式

参考阅读1
参考阅读2

参考定义

Encapsulate a request as an object, thereby letting users parameterize clients with different requests, queue or log requests, and support undoable operations.

命令模式是在我们正常使用 按下按键–触发人物移动 的逻辑中间,(用一个命令类)增加一层解析层,处理不同按键对于的控制逻辑,还可以方便地实现命令的撤销功能

以命令行程序为例,模拟一下按键控制人物移动的情况

命令类 Command 等下补充


模拟人物控制器类 PlayerController

Program 基本逻辑:读取用户输入、打印信息

PlayerController 的成员方法:处理输入到命令的执行或撤销 Input 、解析命令 GetCommand 、具体命令的操作内容 Fire MoveX 等

// command 命令模式
// 命令就是包装在对象中的方法,在没有闭包的语言中模拟闭包的方式
// http://gameprogrammingpatterns.com/command.html
using System;
using System.Threading;
using System.Collections.Generic;

namespace command
{
    class Program
    {
        public static bool gameEnd = false;
        static void Main()
        {
            PlayerController player = new PlayerController();
            while (true)
            {
                // 模拟 fixupdate 0.02 秒更新一次
                Thread.Sleep(2);
                player.Input();
                Console.WriteLine("----pos: " + player.pos[0].ToString() + " , " + player.pos[1].ToString() + " mono: " + player.mono);
                if (gameEnd)
                {
                    break;
                }
            }
        }
    }
    public class PlayerController
    {
        public int[] pos = { 0, 0 };
        public int mono = 10;
        Stack<Command> cmdHistory = new Stack<Command>();
        // 命令模式 消除了直接方法调用的耦合关系,将需要操作的数据传递给其他类
        public void Input()
        {
            ConsoleKeyInfo key = Console.ReadKey();
            Command? cmd = GetCommand(key.Key);
            // 如果有命令
            if (cmd != null)
            {
                // 在命令类中直接调用对应的执行命令方法
                cmd.execute();
                // 可以撤销2次
                if (cmdHistory.Count < 2)
                {
                    cmdHistory.Push(cmd);
                }
            }
        }
        public Command? GetCommand(ConsoleKey key)
        {
            if (key == ConsoleKey.A)
            {
                // 生成并初始化一个移动命令
                return new MoveXCommand(this, -1);
            }
            else if (key == ConsoleKey.D)
            {
                return new MoveXCommand(this, 1);
            }
            else if (key == ConsoleKey.Spacebar)
            {
                // 直接调用
                // Fire();
                // 返回命令的基类派生的开火命令类
                return new FireCommand(this, 3);
            }
            else if (key == ConsoleKey.Q)
            {
                return new ExitCommand();
            }
            else if (key == ConsoleKey.Z)
            {
                if (cmdHistory.Count > 0)
                {
                    cmdHistory.Pop().undo();
                }
                return null;
            }
            else
            {
                return null;
            }
        }
        public void MoveTo(int x, int y)
        {
            pos[0] = x;
            pos[1] = y;
        }
        public void Fire(int amount)
        {
            mono -= amount;
        }
    }
}

命令基类:声明了执行命令、撤销命令的虚方法
命令类:声明了移动、开火、退出的命令

namespace command
{
    public class Command
    {
        public virtual void execute() { }
        public virtual void undo() { }
    }
    class MoveXCommand : Command
    {
        PlayerController player;
        int beforeX = 0;
        int beforeY = 0;
        int dx = 0;
        public MoveXCommand(PlayerController player, int x)
        {
            this.player = player;
            this.dx = x * 3;
        }
        public override void execute()
        {
            base.execute();
            beforeX = player.pos[0];
            beforeY = player.pos[1];

            player.MoveTo(player.pos[0] + dx, player.pos[1]);
        }
        // 撤销移动操作
        public override void undo()
        {
            base.undo();
            player.MoveTo(beforeX, beforeY);
        }
    }
    class FireCommand : Command
    {
        PlayerController player;
        int useNum;
        public FireCommand(PlayerController player, int useNum)
        {
            this.player = player;
            this.useNum = useNum;
        }
        public override void execute()
        {
            base.execute();
            player.Fire(useNum);
        }
    }
    class ExitCommand : Command
    {
        public override void execute()
        {
            base.execute();
            Program.gameEnd = true;
        }
    }
}

经过一层中间层的处理,我们将玩家的输入和要执行的命令进行了隔离。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值