【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. ...
随机推荐
- NOIP模拟测试17&18
NOIP模拟测试17&18 17-T1 给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是? 特判比值为1的情况,预处理比值2~1000的 ...
- Spring AOP框架 AspectJ
1 AspectJ简介 v AspectJ是一个基于Java语言的AOP框架 v Spring2.0以后新增了对AspectJ切点表达式支持 v @AspectJ 是AspectJ1.5新增功能 ...
- python库--tensorflow--数学函数
官方API(需FQ) 中文API 方法 返回值类型 参数 说明 算数运算符 .add() Tensor x, y, name=N 加法(若x,y都为tensor, 数据类型需一致, 以下所有x,y都如 ...
- ASP.NET Core Web API 教程 - Project Configuration
ASP.NET Core Web API 教程 本系列文章主要参考了<Ultimate ASP.NET Core 3 Web API>一书,我对原文进行了翻译,同时适当删减.修改了一部分内 ...
- JavaScrip中 Array.reduce()
数组的方法 reduce() reduce方法在数组的每一项元素上都会执行回调函数. 语法:array.reduce( callBack [ , init] ) // 语法arrary.reduce ...
- Elasticsearch(ES)的滚动搜索与批量操作
1. 概述 今天我们来聊一下Elasticsearch(ES)的滚动搜索与批量操作. 2. Elasticsearch(ES)的滚动搜索 2.1 概述 滚动搜索我们经常能够用到,例如:推荐列表,此类 ...
- Spring Cloud Hystrix 学习(一)
在学习Hystrix之前,首先引入一个问题场景,服务雪崩.如下图所示: 可以看到,三个入口服务A.B.C最终都会请求到服务T.当服务T的请求过载,打满CPU都无法匹配请求的频率时,同步调用的上级服务就 ...
- PHP中的文件系统函数(三)
总算来到我们最关心的部分了,也就是 f 相关函数的操作.基本上大部分的文件操作都是以今天学习的这些内容为基础的,话不多说,我们就一个一个的来学习学习吧. 文件读取 文件的读取其实非常简单,fopen( ...
- PHP设计模式之模板方法模式
模板方法模式,也是我们经常会在不经意间有会用到的模式之一.这个模式是对继承的最好诠释.当子类中有重复的动作时,将他们提取出来,放在父类中进行统一的处理,这就是模板方法模式的最简单通俗的解释.就像我们平 ...
- Docker系列(10)- 常用命令小结
#橙色前面笔记已记录,黑色后面笔记将完善#勤加练习!!!attach Attach to a running container # 当前 shell 下 attach 连接指定运行镜像 build ...