概述

描述

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

套路

  • Context(环境类)

    负责使用算法策略,其中维持了一个抽象策略类的引用实例。
  • Strategy(抽象策略类)

    所有策略类的父类,为所支持的策略算法声明了抽象方法。它既可以是抽象类也可以是接口
  • ConcreteStrategy(具体策略类)

    实现了在抽象策略类中声明的方法。
  • 策略模式可以和简单工厂模式搭配使用

使用场景

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

优缺点

  • 优点

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

UE4 实践

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

    • 假定我们有多个职业和多种武器:战士(刀、剑)、法师(短魔杖、长法杖)、弓箭手(长弓、连弩)
    • 想想怎么实现角色使用武器,武器采用抽象继承或接口的方式,似乎有意无意,都会有策略模式的影子
    • 如果后面还要追加角色使用棍、棒、斧、钺、枪呢
  • 创建策略抽象类、具体类 —— 武器,剑、刀、长弓、无武器

    UCLASS(Abstract) // 抽象策略类 —— 武器
    class DESIGNPATTERNS_API UWeapon : public UObject
    {
    GENERATED_BODY()
    public:
    virtual void UseWeapon() {}
    }; UCLASS() // 具体策略类 —— 剑
    class DESIGNPATTERNS_API USword : public UWeapon
    {
    GENERATED_BODY()
    public:
    virtual void UseWeapon() override {
    UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 长剑已装备"));
    }
    }; UCLASS() // 具体策略类 —— 刀
    class DESIGNPATTERNS_API UMachete : public UWeapon
    {
    GENERATED_BODY()
    public:
    virtual void UseWeapon() override {
    UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 大刀已装备"));
    }
    }; UCLASS() // 具体策略类 —— 无武器
    class DESIGNPATTERNS_API UNoWapon : public UWeapon
    {
    GENERATED_BODY()
    public:
    virtual void UseWeapon() override {
    UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 赤手空拳"));
    }
    }; UCLASS() // 具体策略类 —— 长弓
    class DESIGNPATTERNS_API ULongbow : public UWeapon
    {
    GENERATED_BODY()
    public:
    virtual void UseWeapon() override {
    UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 长弓已装备"));
    }
    };
  • 创建环境类,采用继承的方式创建不同的角色类,此处有战士和弓箭手

    UCLASS(Abstract) // 环境抽象类 —— 角色
    class DESIGNPATTERNS_API UHero : public UObject
    {
    GENERATED_BODY()
    public:
    // 使用策略 —— 使用武器
    virtual void UseWeapon() {
    if (m_pWeapon)
    {
    m_pWeapon->UseWeapon();
    }
    }
    // 更换策略 —— 更换武器
    virtual void ChangeWeapon(UWeapon* pWeapon ) {
    m_pWeapon = pWeapon;
    UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 武器已更换"));
    } protected:
    UPROPERTY()
    UWeapon* m_pWeapon;
    }; UCLASS() // 环境类 —— 战士
    class DESIGNPATTERNS_API UWarrior : public UHero
    {
    GENERATED_BODY()
    public:
    UWarrior() { // 为不同角色初始化武器
    m_pWeapon = NewObject<USword>();
    UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 这是一个战士"));
    }
    }; UCLASS() // 环境类 —— 弓箭手
    class DESIGNPATTERNS_API UArcher : public UHero
    {
    GENERATED_BODY()
    public:
    UArcher() { // 为不同角色初始化武器
    m_pWeapon = NewObject<ULongbow>();
    UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" 这是一个弓箭手"));
    }
    };
  • 调用测试

    UCLASS()
    class DESIGNPATTERNS_API AStrategyTestActor : public AActor
    {
    GENERATED_BODY() public:
    // Sets default values for this actor's properties
    AStrategyTestActor(); protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override { // 创建战士
    UWarrior* Warrior = NewObject<UWarrior>();
    // 使用策略 —— 使用武器
    Warrior->UseWeapon(); // 更换策略 —— 更换武器
    Warrior->ChangeWeapon(NewObject<UMachete>());
    Warrior->UseWeapon(); // 更换策略,不使用武器
    Warrior->ChangeWeapon(NewObject<UNoWapon>());
    Warrior->UseWeapon(); UE_LOG(LogTemp, Warning, TEXT("---------------------------------------"));
    // 创建弓箭手
    UArcher* Archer = NewObject<UArcher>();
    // 使用策略 —— 使用武器
    Archer->UseWeapon(); // 更换策略,不使用武器
    Archer->ChangeWeapon(NewObject<UNoWapon>());
    Archer->UseWeapon();
    }
    };
  • 调式输出

    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 大刀已装备

参考

【UE4 设计模式】策略模式 Strategy Pattern的更多相关文章

  1. 设计模式 - 策略模式(Strategy Pattern) 具体解释

    策略模式(Strategy Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26577879 本文版权全 ...

  2. 设计模式——策略模式(Strategy Pattern)

    写在前面: 直接将书中的例子用来作为记录自己学习的成果,不知道这样好不好,如果给原作者带来什么不利的影响不妨告知一声,我及时删掉. UML图: 抽象策略:Strategy package com.cn ...

  3. C#设计模式——策略模式(Strategy Pattern)

    一.概述我们来实现一个企业的工资系统,该企业中不同级别的员工工资算法都不相同,针对该问题,最容易想到的莫过于在代码中堆积一大堆if…else…语句或者是switch…case…语句.如果该企业中不同级 ...

  4. 24种设计模式-策略模式(Strategy Pattern)

    一.优点: 1. 策略模式提供了管理相关的算法族的办法.策略类的等级结构定义了一个算法或行为族.恰当使用继承可以把公共的代码转移到父类里面,从而避免重复的代码. 2. 策略模式提供了可以替换继承关系的 ...

  5. 设计模式(一):“穿越火线”中的“策略模式”(Strategy Pattern)

    在前段时间呢陆陆续续的更新了一系列关于重构的文章.在重构我们既有的代码时,往往会用到设计模式.在之前重构系列的博客中,我们在重构时用到了“工厂模式”.“策略模式”.“状态模式”等.当然在重构时,有的地 ...

  6. 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)

    原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabc ...

  7. 反馈法学习设计模式(一)——策略模式Strategy Pattern

    简介(Introduction) 之前学习Java8实战时,遇到一个很好的策略模式示例.便想着借着这个示例结合反馈式的方法来,学习策略设计模式,也以便后面反复琢磨学习. 首先我们通过练习,逐步写出符合 ...

  8. HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern)

    策略模式(Strategy Pattern): 定义了了算法簇,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户端. 第一个设计原则:找出应用中可能需要变化之处,把他们独立 ...

  9. 8.6 GOF设计模式四: 策略模式… Strategy Pattern

    策略模式… Strategy Pattern  在POS系统中,有时需要实行价格优惠, 该如何处理?  对普通客户或新客户报全价  对老客户统一折扣5%  对大客户统一折扣10%  注:课件 ...

  10. 二十四种设计模式:策略模式(Strategy Pattern)

    策略模式(Strategy Pattern) 介绍定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.本模式使得算法的变化可独立于使用它的客户. 示例有一个Message实体类,对它的操作有 ...

随机推荐

  1. leetcode数组典型题目小结

    数组与矩阵 数组与矩阵的基本知识: 1.数组:数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按有序的形式组织起来的一种形式. 首先,数组会利用索引来记录每个元素在数组中的位置,且在大多数 ...

  2. vs code使用git---http方式

    1.从git上复制http路径 2.在vs code的工作区新建文件夹 3.选择添加远程储存库 4.输入复制的git路径然后命名远程储存库名称   5.选择从所有远程储存库中拉取分支 6.选择分支,切 ...

  3. LVS负载均衡集群--NAT模式部署

    目录: 一.企业群集应用概述 二.负载均衡群集架构 三.负载均衡群集工作模式分析 四.关于LVS虚拟服务器 五.NAT模式 LVS负载均衡群集部署 一.企业群集应用概述 1.群集的含义 Cluster ...

  4. 计算机基础知识以及java JDK、JRE

    计算机 计算机(Computer)全称:电子计算机,是一种能够按照程序运行,自动.高速处理海量数据的现代化智能电子设备.由硬件和软件所组成,没有安装任何软件的计算机称为裸机.常见的形式有台式计算机.笔 ...

  5. Windows安装Docker & Docker-Compose & 配置docker私有仓库

    一定要给windows先创建软连接,不然系统盘会爆表的: mklink /j .docker D:\Administrator\.docker Win7安装Docker Dockerfile # FR ...

  6. 1.Java 基础

    1. JDK 和 JRE 有什么区别? jdk:开发工具包,jre:java运行环境 jdk包含了jre和java开发环境,如编译java源码的编译器javac,还包含了许多java程序调试和分析的工 ...

  7. POJ3625Building Roads

    Building Roads Description Farmer John had just acquired several new farms! He wants to connect the ...

  8. RestFul的认识与详解

    RestFul :是一种软件架构风格,设计风格,而不是标准.提供了一组设计原则和约束条件. 简单概述: REST -- REpresentational State Transfer 直接翻译:表现层 ...

  9. mysql事务干货详解

    说明: mysql是现在行业中流行的关系型数据库,它的核心是存储引擎.mysql的存储引擎有很多种我们可以通过命令查看如下 SHOW ENGINES 不同版本得到的数据不一样,我们今天说的事务是在 M ...

  10. 如何实现Orchard Core CMS的全文索引

    Orchard Core提供了Lucene功能,允许您在网站上进行全文搜索.大多数情况下,在运行博客或简单的代理网站时,您可能需要在页面内容中进行搜索.在Orchard Core中,您可以使用Liqu ...