参考材料
1. 【UE4 设计模式】策略模式 Strategy Pattern
2. 模板模式
1. 概述
1.1 描述
$\cdot$ 在模板模式(Template Pattern) 中, 一个抽象类公开定义了执行它的方法的方式/ 模板. 它的子类可以按需要重写方法实现, 但调用将以抽象类中定义的方式进行. 这种类型的设计模式属于行为型模式.
1.2 套路
$\cdot$ 实现方式:
$\\$ 1) 定义抽象父类: 包含模板方法和一些抽象方法或具体方法.
$\\$ 2) 实现子类: 继承抽象父类并实现抽象方法, 不改变算法结构.
$\cdot$ 关键代码:
$\\$ 1) 模板方法: 在抽象父类中定义, 调用抽象方法和具体方法.
$\\$ 2) 抽象方法: 由子类实现, 代表算法的可变部分.
$\\$ 3) 具体方法: 在抽象父类中实现, 代表算法的不变部分.
$\cdot$ 结构:
$\\$ 包含的几个主要角色:
$\\$ 1) 抽象父类(Abstract Class): 定义了模板方法和一些抽象方法或具体方法.
$\\$ 2) 具体子类(Concrete Classes): 继承自抽象父类, 并实现抽象方法.
$\\$ 3) 钩子方法(Hook Method)(可选): 在抽象父类中定义, 可以被子类重写, 以影响模板方法的行为.
$\\$ 4) 客户端(Client)(可选): 使用抽象父类和具体子类, 无需关心模板方法的细节.
1.3 使用场景
$\cdot$ 当存在一些通用的方法, 可以在多个子类中共用时.
1.4 优缺点
$\cdot$ 优点:
$\\$ 1) 封装不变部分: 算法的不变部分被封装在父类中.
$\\$ 2) 扩展可变部分: 子类可以扩展或修改算法的可变部分.
$\\$ 3) 提取公共代码: 减少代码重复, 便于维护.
$\cdot$ 缺点:
$\\$ 1) 类数目增加: 每个不同的实现都需要一个子类, 可能导致系统庞大.
2. UE5实践
我们将创建一个定义操作的FGame抽象类, 其中, 模板方法设置为final, 这样它就不会被重写. FCricket和FFootball是扩展了FGame的实体类, 它们重写了抽象类的方法.
$\\$ 我们使用FGame来演示模板模式的用法.
2.1 步骤1
创建一个抽象类, 它的模板方法被设置为final.
#pragma once
class FGame
{
virtual void Initialize() = 0;
virtual void StartPlay() = 0;
virtual void EndPlay() = 0;
// 模板
virtual void Play() final
{
// 初始化游戏
Initialize();
// 开始游戏
StartPlay();
// 结束游戏
EndPlay();
}
};
2.2 步骤2
创建扩展了上述类的实体类.
#pragma once
#include "Game.h"
#include "CoreMinimal.h"
class FCricket final : public FGame
{
virtual void EndPlay() override
{
UE_LOG(LogTemp, Log, TEXT("Cricket Game Finished!"));
}
virtual void Initialize() override
{
UE_LOG(LogTemp, Log, TEXT("Cricket Game Initialized! Start playing."));
}
virtual void StartPlay() override
{
UE_LOG(LogTemp, Log, TEXT("Cricket Game Started. Enjoy the game!"));
}
};
#pragma once
#include "Game.h"
#include "CoreMinimal.h"
class FFootball final : public FGame
{
virtual void EndPlay() override
{
UE_LOG(LogTemp, Log, TEXT("Football Game Finished!"));
}
virtual void Initialize() override
{
UE_LOG(LogTemp, Log, TEXT("Football Game Initialized! Start playing."));
}
virtual void StartPlay() override
{
UE_LOG(LogTemp, Log, TEXT("Football Game Started. Enjoy the game!"));
}
};
2.3 步骤3
使用FGame的模板方法Play()来演示游戏的定义方式.
#include "Circket.h"
#incluce "Football.h"
int main()
{
FGame* GameInstance = new FCricket();
GameInstance->Play();
delete GameInstance;
GameInstance = new FFootball();
GameInstance->Play();
delete GameInstance;
GameInstance = nullptr;
return 0;
}