• UE4 C++设计模式:策略模式(Strategy Pattern)


    目录

    描述

    套路

    使用场景

    优缺点

    UE4实践

    创建策略抽象类

    创建具体策略类

    创建环境类-角色

    创建具体环境(角色)类


    描述

    • 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们可以互相替换。
    • 策略模式让算法的变化不会影响到其他使用算法的客户

    套路

    • Context(环境类)
      • 负责使用算法策略,其中维持了一个抽象策略类的引用实例
    • Strategy(抽象策略类)
      • 所有策略类的父类,为所支持的策略算法声明了抽象方法
    • ConcreteStrategy(具体抽象类)
      • 实现了在抽象策略类中声明的方法
    • 策略模式可以和简单工厂模式搭配使用

    使用场景

    • 如果一个系统里有许多类,区别仅在于他们的行为,那么使用策略模式可以动态的让一个对象在许多行为中选择一种行为
    • 一个系统需要动态的在几种算法中选择一种
    • 如果一个对象有很多行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现
    • 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性
    • 示例:
      • 电影出票多种折扣方式、Steam游戏多种折扣方式,多种折扣策略
      • 多种登录方法(微信登录、手机号码登录、邮箱登录、扫码登录),多种登录策略
      • 多种支付方式(微信支付、支付宝、ApplePay、银联支付),多种支付策略
      • 不同英雄、武器伤害计算方式
      • 不同职业(种族),不同的武器

    优缺点

    • 优点
      • 提供对开闭原则的完美支持,用户可以在不修改原有系统基础上选择具体算法或行为,也可以灵活的增加新算法或行为
      • 避免了多重的if-else条件选择语句,利于系统的维护
      • 提供了一种算法的复用机制,不同的环境类可以方便的复用这些策略类
    • 缺点
      • 客户端必须知道所有策略类,并自定决定使用哪一个策略
      • 策略模式将产生很多策略类,可以通过享元模式在一定程度上减少对象的数量

    UE4实践

    实现不同职业(种族),使用不同的武器

    创建策略抽象类

    1. UCLASS(Abstract) // 抽象策略类 —— 武器
    2. class DESIGNPATTERNS_API UWeapon : public UObject
    3. {
    4. GENERATED_BODY()
    5. public:
    6. virtual void UseWeapon() {}
    7. };

    创建具体策略类

    1. UCLASS() // 具体策略类 —— 剑
    2. class DESIGNPATTERNS_API USword : public UWeapon
    3. {
    4. GENERATED_BODY()
    5. public:
    6. virtual void UseWeapon() override {
    7. UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 长剑已装备"));
    8. }
    9. };
    1. UCLASS() // 具体策略类 —— 刀
    2. class DESIGNPATTERNS_API UMachete : public UWeapon
    3. {
    4. GENERATED_BODY()
    5. public:
    6. virtual void UseWeapon() override {
    7. UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 大刀已装备"));
    8. }
    9. };
    1. UCLASS() // 具体策略类 —— 无武器
    2. class DESIGNPATTERNS_API UNoWapon : public UWeapon
    3. {
    4. GENERATED_BODY()
    5. public:
    6. virtual void UseWeapon() override {
    7. UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 赤手空拳"));
    8. }
    9. };
    1. UCLASS() // 具体策略类 —— 长弓
    2. class DESIGNPATTERNS_API ULongbow : public UWeapon
    3. {
    4. GENERATED_BODY()
    5. public:
    6. virtual void UseWeapon() override {
    7. UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 长弓已装备"));
    8. }
    9. };

    创建环境类-角色

    1. UCLASS(Abstract) // 环境抽象类 —— 角色
    2. class DESIGNPATTERNS_API UHero : public UObject
    3. {
    4. GENERATED_BODY()
    5. public:
    6. // 使用策略 —— 使用武器
    7. virtual void UseWeapon() {
    8. if (m_pWeapon)
    9. {
    10. m_pWeapon->UseWeapon();
    11. }
    12. }
    13. // 更换策略 —— 更换武器
    14. virtual void ChangeWeapon(UWeapon* pWeapon ) {
    15. m_pWeapon = pWeapon;
    16. UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 武器已更换"));
    17. }
    18. protected:
    19. UPROPERTY()
    20. UWeapon* m_pWeapon;
    21. };

    创建具体环境(角色)类

    1. UCLASS() // 环境类 —— 战士
    2. class DESIGNPATTERNS_API UWarrior : public UHero
    3. {
    4. GENERATED_BODY()
    5. public:
    6. UWarrior() { // 为不同角色初始化武器
    7. m_pWeapon = NewObject();
    8. UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 这是一个战士"));
    9. }
    10. };
    1. UCLASS() // 环境类 —— 弓箭手
    2. class DESIGNPATTERNS_API UArcher : public UHero
    3. {
    4. GENERATED_BODY()
    5. public:
    6. UArcher() { // 为不同角色初始化武器
    7. m_pWeapon = NewObject();
    8. UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 这是一个弓箭手"));
    9. }
    10. };

    测试

    1. UCLASS()
    2. class DESIGNPATTERNS_API AStrategyTestActor : public AActor
    3. {
    4. GENERATED_BODY()
    5. public:
    6. // Sets default values for this actor's properties
    7. AStrategyTestActor();
    8. protected:
    9. // Called when the game starts or when spawned
    10. virtual void BeginPlay() override {
    11. // 创建战士
    12. UWarrior* Warrior = NewObject();
    13. // 使用策略 —— 使用武器
    14. Warrior->UseWeapon();
    15. // 更换策略 —— 更换武器
    16. Warrior->ChangeWeapon(NewObject());
    17. Warrior->UseWeapon();
    18. // 更换策略,不使用武器
    19. Warrior->ChangeWeapon(NewObject());
    20. Warrior->UseWeapon();
    21. UE_LOG(LogTemp, Warning, TEXT("---------------------------------------"));
    22. // 创建弓箭手
    23. UArcher* Archer = NewObject();
    24. // 使用策略 —— 使用武器
    25. Archer->UseWeapon();
    26. // 更换策略,不使用武器
    27. Archer->ChangeWeapon(NewObject());
    28. Archer->UseWeapon();
    29. }
    30. };

    LogTemp: Warning: UWarrior::UWarrior 这是一个战士
    LogTemp: Warning: USword::UseWeapon 长剑已装备
    LogTemp: Warning: UHero::ChangeWeapon 武器已更换
    LogTemp: Warning: UMachete::UseWeapon 大刀已装备
    LogTemp: Warning: UHero::ChangeWeapon 武器已更换
    LogTemp: Warning: UMachete::UseWeapon 大刀已装备
    LogTemp: Warning: ---------------------------------------
    LogTemp: Warning: UArcher::UArcher 这是一个弓箭手
    LogTemp: Warning: ULongbow::UseWeapon 长弓已装备
    LogTemp: Warning: UHero::ChangeWeapon 武器已更换
    LogTemp: Warning: UMachete::UseWeapon 大刀已装备
     

    [策略模式]在游戏开发中的应用 - 唐衣可俊 - 博客园 (cnblogs.com) 

  • 相关阅读:
    Java常用类(一)
    Redis源码与设计剖析 -- 8.对象系统
    Java基础(四)
    centos 安装多个版本的php并切换
    Linux权限与用户
    【HCSD零代码云上开发】零代码入门微信小程序和物联网
    北理工操作系统实验合集 | API解读与例子(持续更新)
    Git仓库迁移实操(附批量迁移脚本)
    juc详解
    给ShardingSphere提了个PR
  • 原文地址:https://blog.csdn.net/Jason6620/article/details/126545024