C# 设计模式(二)策略模式(unity演示)


1.引言

知识准备:

  • C# 的多态知识
  • unity的基础知识

  本文要介绍的策略模式就是对策略进行抽象,策略的意思就是方法,所以也就是对方法的抽象,下面具体分享下我对策略模式的理解。

2. 定义

策略模式(The Strategy pattern)
  定义:定义算法族,分别封装起来,让它们之前可以互相替换,此模式让算法的变化独立于使用算法的客户。也就是说策略模式是针对一组算法,将每个算法封装到具有公共接口的独立的类中,从而使它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

3. 模式结构

  策略模式其实是对算法的包装,是把使用算法的责任和算法本身分割开,委派给不同的对象负责。策略模式通常把一系列的算法包装到一系列的策略类里面。用一句话慨括策略模式就是——“将每个算法封装到不同的策略类中,使得它们可以互换”。
下面是策略模式的类图:
这里写图片描述

从上图可以看出,策略模式由三部分组成:抽象策略角色(Strategy)、具体策略角色(具体算法)和环境角色(Context类)。

  • 抽象策略角色(Strategy):这个类定义了所有支持的算法的公共接口,这是一个抽象角色,通常由一个接口或抽象类来实现;
  • 具体策略角色(StrategyA/B/C):具体的策略类封装了具体的算法或行为,继承于策略类(Strategy);
  • 环境角色(Context类):持有一个Strategy类的引用,即该类用一个ContextStrategy来配置,维护一个对具体策略的引用。

4. 类图实现

具体实现代码如下所示:
抽象策略角色(Strategy)

/// <summary>
///抽象算法类 
/// </summary>
public abstract  class Strategy
{
    public abstract void AlgorithmInterface();
}

具体策略角色(StrategyA/B/C)

/// <summary>
///算法A类 
/// </summary>
public class StrategyA:Strategy
{
    /// <summary>
    ///算法A实现算法
    /// </summary>
    public override void AlgorithmInterface()
    {
        Console.WriteLine("算法A");
    }
}

/// <summary>
///算法B类 
/// </summary>
public class StrategyB:Strategy
{
    /// <summary>
    ///算法A实现算法
    /// </summary>
    public override void AlgorithmInterface()
    {
        Console.WriteLine("算法B");
    }
}
/// <summary>
///算法C类 
/// </summary>
public class StrategyC:Strategy
{
    /// <summary>
    ///算法C实现算法
    /// </summary>
    public override void AlgorithmInterface()
    {
        Console.WriteLine("算法C");
    }
}

环境角色(Context类)

Class Context
{
    Strategy st;
    public Context(Strategy  strategy )
    {
        this.st = strategy;
    }

    ///<summary>
    ///上下文接口
    ///<summary>
    public void ContextInterface()
    {
        st.AlgorithmInterface();
    }
}

测试以下:

Context ct = new Context(new StrategyA());
ct.ContextInterface();

Console.ReadKey();

5. 策略者模式在.NET中应用

  在.NET Framework中也不乏策略模式的应用例子。例如,在.NET中,为集合类型ArrayList和List提供的排序功能,其中实现就利用了策略模式,定义了IComparer接口来对比较算法进行封装,实现IComparer接口的类可以是顺序,或逆序地比较两个对象的大小,具体.NET中的实现可以使用反编译工具查看List.Sort(IComparer)的实现。其中List就是承担着环境角色,而IComparer接口承担着抽象策略角色,具体的策略角色就是实现了IComparer接口的类,List类本身实现了存在实现了该接口的类,我们可以自定义继承与该接口的具体策略类。

6. 策略者模式的适用场景

在下面的情况下可以考虑使用策略模式:

  • 一个系统需要动态地在几种算法中选择一种的情况下。那么这些算法可以包装到一个个具体的算法类里面,并为这些具体的算法类提供一个统一的接口。
  • 如果一个对象有很多的行为,如果不使用合适的模式,这些行为就只好使用多重的if-else语句来实现,此时,可以使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象涉及的概念。

7. 策略者模式的优缺点

1.策略模式的主要优点有:

  • 策略类之间可以自由切换。由于策略类都实现同一个接口,所以使它们之间可以自由切换;
  • 易于扩展。增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码;
  • 避免使用多重条件选择语句,充分体现面向对象设计思想。

2.策略模式的主要缺点有:

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这点可以考虑使用IOC容器和依赖注入的方式来解决,关于IOC容器和依赖注入(Dependency Inject)的文章可以参考:IoC 容器和Dependency Injection 模式;
  • 策略模式会造成很多的策略类。

8. 应用举例(unity)

抽象基类

using UnityEngine;

/// <summary>
/// 抽象移动类
/// </summary>
public abstract class IMove {
    /// <summary>
    /// 移动方法
    /// </summary>
    /// <param name="obj">要移动的物体</param>
    public abstract void Move(GameObject obj);
}

上下移动

using UnityEngine;

/// <summary>
/// 具体移动类 上下移动
/// </summary>
public class Move1 : IMove
{
    /// <summary>
    /// 重写移动类 上下移动
    /// </summary>
    /// <param name="obj"></param>
    public override void Move(GameObject obj)
    {
        obj.transform.Translate(0, 1 * Time.deltaTime, 0, Space.Self);
    }
}

左右移动

using UnityEngine;

/// <summary>
/// 具体移动类 左右移动
/// </summary>
public class Move2 : IMove
{
    /// <summary>
    /// 重写移动类 左右移动
    /// </summary>
    /// <param name="obj"></param>
    public override void Move(GameObject obj)
    {
        obj.transform.Translate(1 * Time.deltaTime, 0, 0, Space.Self);
    }
}

游戏物体类

using UnityEngine;

public class MyCube {

    /// <summary>
    /// 方块
    /// </summary>
    private GameObject myCube;

    /// <summary>
    /// 移动
    /// </summary>
    private IMove move;

    public MyCube(GameObject obj)
    {
        this.myCube = obj;
        this.move = new Move1();
    }

    /// <summary>
    /// myCube移动
    /// </summary>
    public void Move()
    {
        move.Move(myCube);
    }

    /// <summary>
    /// 设置myCube的移动方向
    /// </summary>
    /// <param name="mo"></param>
    public void SetImoveBehavior(IMove mo)
    {
        move = mo;
    }

}

游戏物体控制类

using UnityEngine;

public class CubeControl : MonoBehaviour
{

    private GameObject obj;
    MyCube myCube;
    void Start()
    {
        obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
        myCube = new MyCube(obj);
    }

    // Update is called once per frame
    void Update()
    {
        myCube.Move();
    }

    public void OnGUI()
    {        
        if (GUILayout.Button("点击上运动"))
        {    
            myCube.SetImoveBehavior(new Move1());
        }
        if (GUILayout.Button("点击向右运动"))
        {
            myCube.SetImoveBehavior(new Move2());
        }
    }
}

9. 总结

  到这里,策略模式的介绍就结束了,策略模式主要是对方法的封装,把一系列方法封装到一系列的策略类中,从而使不同的策略类可以自由切换和避免在系统使用多重条件选择语句来选择针对不同情况来选择不同的方法。
  

10. unity工程下载

本次演示版本Unity 5.6.3f1 (64-bit),需要下载的朋友,请点击此处下载点击此处下载


The End
  好了,今天的分享就到这里,如有不足之处,还望大家及时指正,随时欢迎探讨交流!!!


喜欢的朋友们,请帮顶、点赞、评论!您的肯定是我写作的不竭动力!

相关阅读
C# 23种设计模式(unity演示)

猜你喜欢

转载自blog.csdn.net/lxt610/article/details/80879447