Unity 设计模式-策略模式(Strategy Pattern)详解

策略模式(Strategy Pattern)是一种行为型设计模式,定义了一系列算法,并将每种算法封装到独立的类中,使得它们可以互相替换。策略模式让算法可以在不影响客户端的情况下独立变化,客户端通过与这些策略对象进行交互来执行不同的行为。

在策略模式中,核心思想是将算法的定义和使用分离,使得不同的策略(算法)可以灵活地切换,符合面向对象设计中的开闭原则,即对扩展开放、对修改关闭。

策略模式的结构

  • 策略接口(Strategy Interface):定义所有策略的共同行为,这通常是一个抽象类或接口。
  • 具体策略类(Concrete Strategy):实现策略接口的具体算法。
  • 上下文类(Context Class):维护对某个策略对象的引用,并提供对客户端的接口,允许客户端调用策略算法。

适用场景

  • 避免使用难以维护的多重条件选择语句
  • 当策略中有较为复杂的数据结构或者算法不需要暴露在客户端或者其他时。

在 Unity 中使用 策略模式

在 Unity 中使用策略模式的一个典型应用场景是为游戏角色定义不同的移动方式,例如:走路、跑步、跳跃等。在游戏开发中,不同的角色可能有不同的移动方式。通过策略模式,我们可以将这些不同的移动逻辑封装到独立的策略类中,并动态切换角色的移动方式。

1、通过策略模式实现角色的移动

(1) 定义策略接口

首先定义一个策略接口 IMoveStrategy,它规定所有移动策略都必须实现一个 Move() 方法。

cs 复制代码
public interface IMoveStrategy
{
    void Move(Transform characterTransform);
}

(2) 定义具体策略类

创建几个具体的移动策略类 WalkStrategyRunStrategyJumpStrategy,分别实现不同的移动行为。

cs 复制代码
using UnityEngine;
 
// 走路策略
public class WalkStrategy : IMoveStrategy
{
    public void Move(Transform characterTransform)
    {
        characterTransform.Translate(Vector3.forward * 2f * Time.deltaTime);
        Debug.Log("Character is walking.");
    }
}
 
// 跑步策略
public class RunStrategy : IMoveStrategy
{
    public void Move(Transform characterTransform)
    {
        characterTransform.Translate(Vector3.forward * 5f * Time.deltaTime);
        Debug.Log("Character is running.");
    }
}
 
// 跳跃策略
public class JumpStrategy : IMoveStrategy
{
    public void Move(Transform characterTransform)
    {
        characterTransform.Translate(Vector3.up * 5f * Time.deltaTime);
        Debug.Log("Character is jumping.");
    }
}

(3) 定义上下文类

Character 类作为上下文类,负责维护当前的移动策略,并提供方法来设置不同的移动策略和执行移动操作。

cs 复制代码
using UnityEngine;
 
public class Character : MonoBehaviour
{
    private IMoveStrategy moveStrategy;
 
    // 设置移动策略
    public void SetMoveStrategy(IMoveStrategy strategy)
    {
        moveStrategy = strategy;
    }
 
    // 执行移动
    public void PerformMove()
    {
        if (moveStrategy != null)
        {
            moveStrategy.Move(transform);
        }
        else
        {
            Debug.LogWarning("Move strategy not set!");
        }
    }
}

(4) 客户端代码

GameController 中,我们实例化角色,并动态设置和切换移动策略。

cs 复制代码
using UnityEngine;
 
public class GameController : MonoBehaviour
{
    private Character character;
 
    void Start()
    {
        // 创建角色
        character = gameObject.AddComponent<Character>();
 
        // 初始化为走路策略
        character.SetMoveStrategy(new WalkStrategy());
    }
 
    void Update()
    {
        // 执行移动
        character.PerformMove();
 
        // 根据输入切换策略
        if (Input.GetKeyDown(KeyCode.W))
        {
            character.SetMoveStrategy(new WalkStrategy());
        }
        else if (Input.GetKeyDown(KeyCode.R))
        {
            character.SetMoveStrategy(new RunStrategy());
        }
        else if (Input.GetKeyDown(KeyCode.Space))
        {
            character.SetMoveStrategy(new JumpStrategy());
        }
    }
}

示例解释

  • WalkStrategy:角色以较慢的速度向前移动,模拟走路的行为。
  • RunStrategy:角色以较快的速度向前移动,模拟跑步的行为。
  • JumpStrategy:角色向上跳跃,模拟跳跃的行为。

在 GameController 中,使用键盘输入(W 键、R 键和空格键)来动态切换角色的移动策略。按下相应的键后,角色将切换到走路、跑步或跳跃模式。

通过策略模式,角色的移动方式可以灵活切换,而不需要修改任何核心代码。

策略模式 在 Unity 中的优势是可以动态切换角色行为,如移动、攻击等。通过将不同的移动方式封装到独立的类中,我们可以更方便地扩展系统,并根据游戏需求随时切换策略。

2、通过策略模式实现修改图片的颜色

(1)定义策略接口

首先定义一个抽象类或接口ChangeColor,并且声明一个image参数和ExChangeColor的虚方法

cs 复制代码
using UnityEngine.UI;
public abstract class ChangeColor 
{
    public Image img;
    public virtual void ExChangeColor() { }
}

(2)定义具体策略类

然后创建几个具体的策略类,ChangeColor和ChangeBlue,分别用来改变不同颜色

cs 复制代码
//修改图片颜色为红色
using UnityEngine;
public class ChangeRed : ChangeColor
{
    public override void ExChangeColor()
    {
        img.color = Color.red;
    }
}

-------------------
//修改图片颜色为蓝色
using UnityEngine;
public class ChangeBlue : ChangeColor
{
    public override void ExChangeColor()
    {
        img.color = Color.blue;
    }
}

(3)定义上下文类

维护对strategy 对象的引用,并提供方法来设置不同的操作

cs 复制代码
using UnityEngine.UI;
public class StategyContext 
{
    ChangeColor strategy;
    public StategyContext(ChangeColor strategy,Image img)
    {
        this.strategy = strategy;
        this.strategy.img = img;
    }

    public void StategyContextInterface()
    {
        strategy.ExChangeColor();
    }
}

(4)客户端代码

StategyManager 中,我们实例化角色,并动态设置和切换移动策略。

cs 复制代码
using UnityEngine.UI;
public class StategyManager : MonoBehaviour
{
    [SerializeField] private Image img;
    StategyContext stategyContext;
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.R))
        {
            stategyContext = new StategyContext(new ChangeRed(), img);
            stategyContext.StategyContextInterface();
        }
        if (Input.GetKeyDown(KeyCode.B))
        {
            stategyContext = new StategyContext(new ChangeBlue(), img);
            stategyContext.StategyContextInterface();
        }
    }
}

今天是2024年12月4日

重复一段毒鸡汤来勉励我和你

你的对手在看书

你的仇人在磨刀

你的闺蜜在减肥

隔壁的老王在练腰

而你在干嘛?

相关推荐
Zane19941 天前
一个 new 就能创建对象,为什么还要拆出单例、工厂、建造者、原型四种模式?
设计模式
怕浪猫2 天前
一行命令复刻爆款视频,我把 Hypit 从安装跑到了出片
人工智能·设计模式·程序员
Zane19942 天前
函数式编程里的函数,其实不是你天天写的那个函数——三大编程范式的边界在哪
设计模式
Zane19944 天前
策略模式现在该不该上?一次讲清楚过度设计和设计不足怎么找平衡
设计模式
她说..4 天前
常见设计模式-模板方法模式
java·spring·设计模式·springboot
xiaofeiyang1504 天前
第六章 · 桥接 — 三支毛笔,画出九种颜色
设计模式
Shadow(⊙o⊙)5 天前
OTOL设计模式 One Thread One Loop
服务器·网络·设计模式
sarasuki5 天前
如何让LLM 能在半夜偷偷打开网易云呢?
人工智能·设计模式·agent
小王师傅665 天前
【设计模式】装饰模式(四):框架源码实战——从 Java I/O 到 Spring 到 MyBatis
java·设计模式
执明wa5 天前
Android RecyclerView 多类型, 多种 Item
android·xml·开发语言·设计模式·android studio