【UE4 设计模式】命令模式 Command Pattern
概述
描述
将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
命令模式是一种对象行为型模式,其别名为动作(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的更多相关文章
- 设计模式 - 命令模式(command pattern) 多命令 具体解释
命令模式(command pattern) 多命令 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.csdn.ne ...
- 设计模式 - 命令模式(command pattern) 具体解释
命令模式(command pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 命令模式(command pattern) : 将请求封装成对 ...
- 设计模式 - 命令模式(command pattern) 宏命令(macro command) 具体解释
命令模式(command pattern) 宏命令(macro command) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考: 命名模式(撤销) ...
- 设计模式 - 命令模式(command pattern) 撤销(undo) 具体解释
命令模式(command pattern) 撤销(undo) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.cs ...
- C#设计模式——命令模式(Command Pattern)
一.概述通常来说,“行为请求者”与“行为实现者”是紧耦合的.但在某些场合,比如要对行为进行“记录.撤销/重做.事务”等处理,这种无法抵御变化的紧耦合是不合适的.在这些情况下,将“行为请求者”与“行为实 ...
- 乐在其中设计模式(C#) - 命令模式(Command Pattern)
原文:乐在其中设计模式(C#) - 命令模式(Command Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 命令模式(Command Pattern) 作者:webabcd ...
- 二十四种设计模式:命令模式(Command Pattern)
命令模式(Command Pattern) 介绍将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可取消的操作. 示例有一个Message实体类,某个 ...
- 设计模式-15命令模式(Command Pattern)
1.模式动机 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使 ...
- 设计模式----行为型模式之命令模式(Command Pattern)
下面来自head first设计模式的命令模式一章节. 定义 将"请求"封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 类图 注: 1. ...
随机推荐
- javaScript知识储备
javaScript知识储备 组成 ECMAScript(核心) 提供语法.变量等,遵循ECMA-262标准 DOM(文档对象模型) 提供操作HTML标签的API,遵循W3C规范 BOM(浏览器对象模 ...
- 「山东省队集训2021 Round 1」 半夜
考虑将 \(X\) 复制一次放到后面再对其长度为 \(n\) 的连续子串和 \(Y\) 求一波 \(\rm{Longest\ Common\ Subsequence}\) 就能得到 \(\Theta( ...
- Linux串口调试详解
测试平台 宿主机平台:Ubuntu 16.04.6 目标机:iMX6ULL 目标机内核:Linux 4.1.15 目标机添加串口设备 一般嵌入式主板的默认镜像可能只配置了调试串口,并用于 consol ...
- RSA及其证明 [原创]
描述RSA的实现步骤介绍文章非常多,但说明并证明其原理,并进而讨论为什么这样设计的文章不多.本人才疏学浅,不敢说理解了R.S.A.三位泰斗的设计初衷,简单就自己的理解写一写,博大家一笑. 以下原创内容 ...
- Sentry 后端监控 - 最佳实践(官方教程)
系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...
- pip国内源设置
在目录 C:\Users\Administrator下新建pip目录 C:\Users\Administrator\pip 添加 pip.ini 文件 pip.ini内容设置为 [global] in ...
- HDU - 2544最短路 (dijkstra算法)
HDU - 2544最短路 Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以 ...
- 变着花样来接参,PHP中接收外部参数的方式
对于PHP这样一个web语言来说,接参是非常重要的一个能力.毕竟从前端表单或异步请求传递上来的数据都要获取到才能进行正常的交互展示.当然,这也是所有能够进行web开发的语言的必备能力.今天我们就来看看 ...
- DS博客作业03--树
这个作业属于哪个班级 数据结构--网络2011/2012 这个作业的地址 DS博客作业03--树 这个作业的目标 学习树结构设计及运算操作 姓名 黄静 目录 0. PTA得分截图 1. 本周学习总结 ...
- Java开发基础平台带集成的审批工作流
前言 activiti工作流,企业erp.oa.hr.crm等审批系统轻松落地,请假审批demo从流程绘制到审批结束实例. 一.项目形式 springboot+vue+activiti集成了activ ...