策略模式:
对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。
比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。
策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
策略模式:
- 定义了一族算法(业务规则);
- 封装了每个算法;
- 这族的算法可互换代替(interchangeable)。
类图如下:
例子:
鸟类, 鸟可以分为许多种,有麻雀,老鹰,乌鸦,鸵鸟等, 我们如何用代码实现他们呢?
首先我们一般会想到用继承, 先定义一个鸟(Bird)基类,并且把他们公共方法和属性封装起来,例如它们都有生命、叫声、飞行等等。
然而对于 “飞” 这个动作, 有些鸟不能飞, 有些可以飞,并且飞的方式也不一样,此时我们怎么办呢?
我们很容易想到可以用继承加重写的方式来实现,大致如下:
using UnityEngine;
using System.Collections;
public class Bird
{
public virtual void Fly()
{
Debug.Log("Can Fly");
}
}
public class Bird1 : Bird
{
public override void Fly()
{
// override
}
}
public class Bird2 : Bird
{
public override void Fly()
{
// override
}
}
public class Bird3 : Bird
{
public override void Fly()
{
// override
}
}
以上虽然功能实现了,但是如果有许多鸟的话, 那岂不是都要重写一遍?
并且代码复用性、扩展性都不高。
此时我们就可以用到策略模式了
把"飞"这个动作独立出来, 封装成 “飞” 的接口,根据不同的方式来实现该接口的类,
代码如下:
public interface IFly
{
string Fly();
}
//不能飞
class CantFly : IFly
{
public string Fly()
{
return "I can't fly";
}
}
//飞行方式一
class Fly1 : IFly
{
public string Fly()
{
return "fly1....";
}
}
//飞行方式二
class Fly2 : IFly
{
public string Fly()
{
return "fly1....";
}
}
//基类
public class Bird
{
//飞行类型
public IFly flyingType;
public string TryToFly()
{
return flyingType.Fly();
}
//设置飞行方式
public void SetFlyingBehavior(IFly newFlyingType)
{
this.flyingType = newFlyingType;
}
}
//鸵鸟
public class Ostrich : Bird
{
public Ostrich()
{
flyingType = new CantFly();
}
}
//老鹰
public class Eagle : Bird
{
public Eagle()
{
flyingType = new Fly1();
}
}
//麻雀
public class Sparrow : Bird
{
public Sparrow()
{
flyingType = new Fly2();
}
}
测试:
void Main()
{
Animal ostrich = new Ostrich();
Animal eagle = new Eagle();
Debug.Log("ostrich: " + sparky.TryToFly());
Debug.Log("eagle: " + tweety.TryToFly());
ostrich.SetFlyingBehavior(new Fly2());
Debug.Log("ostrich: " + ostrich.TryToFly());
Debug.Log("eagle: " + eagle.TryToFly());
}
以上我们就完美的解决我们之前的问题了,每次只要有新的鸟,我们就只需要设计一个对应的的鸟类和飞行类(或者直接用以上有的飞行方式),提高了代码的复用性、扩展性,并且还可以动态设置不同的飞行方式。