概述

描述

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

  • 命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。

  • 建造者模式将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端无需知道复杂对象的内部组成与装配方式,主需要知道所需的建造者即可。类似工厂方法,但是建造者模式返回一个完整的复杂产品,而抽象工厂模式则返回一系列相关的产品。以汽车为例,工厂方法可以看成不同汽车配件的生成,而建造者模式则可以看成时汽车的组装

套路

  • 客户端 Client 

    命令的发起者。确定接下来要执行什么命令。
  • 调用者 Invoker

     命令的管理者,不关心每个命令具体是做什么内容,根据客户端的指示按序执行命令。
  • 抽象命令 Command

    命令接口协议,确定每个命令需要提供的功能,这里要求每个命令类都提供执行方法。
  • 具体命令 ConcreteCommand

    包含执行一个命令所需的所有上下文信息,例如执行接收者的哪个方法,以及方法所需要的参数,甚至命令作为GUI 显示时的相关信息,例如应该显示的图标路径。具体命令类是命令模式中的核心节点,需要重点理解。
  • 接收者 Receiver:命令所对应任务的实际执行者,位于调用链条的末端。

使用场景

  • 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
  • 系统需要在不同的时间指定请求、将请求排队和执行请求。
  • 系统需要将一组操作组合在一起,即支持宏命令
  • 示例
    • 按键、快捷键映射、玩家输入
    • 撤销(Undo)、恢复(Redo),维护命令列表
    • 新手引导

优缺点

  • 优点

    • 降低系统的耦合度。
    • 新的命令可以很容易地加入到系统中。
    • 可以比较容易地设计一个命令队列和宏命令(组合命令)。
    • 可以方便地实现对请求的Undo和Redo。
  • 缺点
    • 使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

UE4 实践

  • 写一个事件触发器,点击地图地点触发场景传送;点击资料片播放过场动画

  • 创建接收者抽象类、具体类 —— 场景传送、触发剧情

    • 此处抽象类非必要,但实际使用可能会有多个派生类多种 action 成员函数被使用
    // 抽象接收者类 Receiver
    UCLASS()
    class DESIGNPATTERNS_API UCmdReceiver : public UObject
    {
    GENERATED_BODY()
    public: virtual void Action() { check(0 && "You must override this"); }
    }; // 具体接收者类 Receiver —— 场景传送
    UCLASS()
    class DESIGNPATTERNS_API ULevelPortal : public UCmdReceiver
    {
    GENERATED_BODY()
    public:
    virtual void Action() override {
    UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 传送到下一个场景"));
    }
    }; // 具体接收者类 Receiver —— 资料片播放
    UCLASS()
    class DESIGNPATTERNS_API UCutscene : public UCmdReceiver
    {
    GENERATED_BODY()
    public:
    virtual void Action() override {
    UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 播放剧情动画"));
    }
    };
  • 抽象命令类、具体命令类 —— 场景传送命令、资料片播放命令

    • 此处 接收者 采用了继承方式,因此和具体命令搭起来,代码显得重复。实际使用时,Execute成员函数可能会重载,调用不同类对象进行处理
    // 抽象命令类
    UCLASS(Abstract)
    class DESIGNPATTERNS_API UCommand : public UObject
    {
    GENERATED_BODY()
    public: void SetReceiver(UCmdReceiver* pCmdReceiver) { m_pCmdReceiver = pCmdReceiver; } // 调用接收者的 Action
    virtual void Execute() {
    if (m_pCmdReceiver)
    {
    m_pCmdReceiver->Action();
    }
    }
    // virtual void undo() protected:
    UCmdReceiver *m_pCmdReceiver;
    }; // 具体命令类 —— 场景传送命令
    UCLASS()
    class DESIGNPATTERNS_API UPortalCommand : public UCommand
    {
    GENERATED_BODY()
    public: // 可重载做些额外的工作
    //virtual void Execute() override { }
    }; // 具体命令类 —— 资料片播放命令
    UCLASS()
    class DESIGNPATTERNS_API UCutsceneCommand : public UCommand
    {
    GENERATED_BODY()
    public: // 可重载做些额外的工作
    //virtual void Execute() override { }
    };
  • 调用者 Invoker

    UCLASS()
    class DESIGNPATTERNS_API ACommandActor : public AActor
    {
    GENERATED_BODY()
    public: void BeginPlay() override { // 创建接收者 场景传送
    ULevelPortal* LevelPortal = NewObject<ULevelPortal>(); // 创建命令对象
    UPortalCommand* PortalCommand = NewObject<UPortalCommand>();
    PortalCommand->SetReceiver(LevelPortal); // this 当做调用者 Invoker
    PortalCommand->Execute(); // 创建接收者 资料片播放
    UCutscene* Cutscene = NewObject<UCutscene>(); // 创建命令对象
    UCutsceneCommand* CutsceneCommand = NewObject<UCutsceneCommand>();
    CutsceneCommand->SetReceiver(Cutscene); // this 当做调用者 Invoker
    CutsceneCommand->Execute();
    }
    };
  • 调式输出

    LogTemp: Warning: ULevelPortal::Action 传送到下一个场景
    LogTemp: Warning: UCutscene::Action 播放剧情动画

参考

【UE4 设计模式】命令模式 Command Pattern的更多相关文章

  1. 设计模式 - 命令模式(command pattern) 多命令 具体解释

    命令模式(command pattern) 多命令 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.csdn.ne ...

  2. 设计模式 - 命令模式(command pattern) 具体解释

    命令模式(command pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 命令模式(command pattern) : 将请求封装成对 ...

  3. 设计模式 - 命令模式(command pattern) 宏命令(macro command) 具体解释

    命令模式(command pattern) 宏命令(macro command) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考: 命名模式(撤销) ...

  4. 设计模式 - 命令模式(command pattern) 撤销(undo) 具体解释

    命令模式(command pattern) 撤销(undo) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.cs ...

  5. C#设计模式——命令模式(Command Pattern)

    一.概述通常来说,“行为请求者”与“行为实现者”是紧耦合的.但在某些场合,比如要对行为进行“记录.撤销/重做.事务”等处理,这种无法抵御变化的紧耦合是不合适的.在这些情况下,将“行为请求者”与“行为实 ...

  6. 乐在其中设计模式(C#) - 命令模式(Command Pattern)

    原文:乐在其中设计模式(C#) - 命令模式(Command Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 命令模式(Command Pattern) 作者:webabcd ...

  7. 二十四种设计模式:命令模式(Command Pattern)

    命令模式(Command Pattern) 介绍将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可取消的操作. 示例有一个Message实体类,某个 ...

  8. 设计模式-15命令模式(Command Pattern)

    1.模式动机 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使 ...

  9. 设计模式----行为型模式之命令模式(Command Pattern)

    下面来自head first设计模式的命令模式一章节. 定义 将"请求"封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 类图 注: 1. ...

随机推荐

  1. B. 2194: 快速傅立叶之二解题报告

    $$\begin{eqnarray}&c[k] = \sum_{i}^{n}a[i]b[i-k] \\&c[k] = \sum_{i}^{n}a[n-i]b[i-k] (倒序保存a) ...

  2. 发那科FANUC机器人视频学习教程

    82课时的全套发那科机器人视频教程,学完可以掌握发那科机械手的使用和编程,需要的加我微信私私聊.X241602 FANUC 是日本一家专门研究数控系统的公司,成立于1956年.是世界上最大的专业数控系 ...

  3. 面试HashMap你都扛不住,还想拿到offer?

    当我们面试Java开发岗位时,面试官问的频率出现最多的问题,就是这个HashMap,不管是传统型公司还是互联公司,HashMap是必问的,所以作者爆肝整理了HashMap的23个问题以及答案,请查收! ...

  4. WPF Prism8.0中注册Nlog日志服务

    无论是Nlog还是Serilog, 它们都提供了如何快速在各类应用程序当中的快速使用方法. 尽管,你现在无论是在WPF或者ASP.NET Core当中, 都可以使用ServiceCollection来 ...

  5. hyperf从零开始构建微服务(二)——构建服务消费者

    阅读目录 构建服务消费者 安装json rpc依赖 安装JSON RPC客户端 server配置 编写业务代码 编写服务消费者类 consumer配置 配置 UserServiceInterface ...

  6. (5)java Spring Cloud+Spring boot+mybatis企业快速开发架构之SpringCloud-Spring Boot简介

    ​Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是简化新 Spring 应用的初始搭建以及开发过程.该框架使用了特定的方式进行配置,从而使开发人员不再需要定义样板化的配置 ...

  7. C# 获得当前方法 和 方法调用链 的 方法

    一个获得方法名的方法,depth表示调用此方法的回溯深度. 比如,A方法调用B方法,B方法调用GetCurrentMethodFullName(2),那么得到的结果是A方法的全名(namespace+ ...

  8. 【MySQL】MySQL基础(SQL语句、约束、数据类型)

    数据库的基本概念 什么是数据库? 用于存储和管理数据的仓库 英文单词为:DataBase,简称DB 数据库的好处? 可以持久化存储数据 方便存储和管理数据 使用了统一的方式操作数据库 -- SQL 常 ...

  9. Mongodb的基本使用及对接多数据源

    mongodb介绍 MongoDB(来自于英文单词"Humongous",中文含义为"庞大")是可以应用于各种规模的企业.各个行业以及各类应用程序的开源数据库. ...

  10. Java学习之随堂笔记系列——day03

    内容回顾:1.标识符和类型转换    1.1 标识符:给类.方法.变量取得名字就是标识符.        命名规则:            1.必须是字母.数字._.$组成            2. ...