3.7.1 模式意图:
如果在系统中需要为某一行为提供多种方案,例如不同的折扣方式;货币不同的汇率;到达某地不同的路线等情况,就可以使用策略模式。
3.7.2 模式概念:
它属于行为型模式,指对象有某个行为,但是在不同的环境中,可以在运行时为行为更改不同的算法。
3.7.3 模式元素:
- 策略抽象(BaseStrategy)
- 策略细节(StrategyWalk、StrategyShip等)
- 使用环境(Context)
3.7.4 代码示例:
public abstract class BaseStrategy
{
public abstract string GetRoute(string from, string to);
}
public class StrategyWalk : BaseStrategy
{
public override string GetRoute(string from, string to)
{
return "步行到达";
}
}
public class StrategyShip : BaseStrategy
{
public override string GetRoute(string from, string to)
{
return "轮船到达";
}
}
public class StrategyTrain : BaseStrategy
{
public override string GetRoute(string from, string to)
{
return "火车到达";
}
}
public class StrategyAirplane : BaseStrategy
{
public override string GetRoute(string from, string to)
{
return "飞机到达";
}
}
public class Context
{
private BaseStrategy baseStrategy;
public Context(BaseStrategy baseStrategy)
{
this.baseStrategy = baseStrategy;
}
public string GetResult(string side1,string side2)
{
return baseStrategy.GetRoute(side1, side2);
}
}
调用示例代码
void Start()
{
BaseStrategy strategy = new StrategyWalk();
Context context = new Context(strategy);
string route = context.GetResult("地点一", "地点二");
Debug.Log(route);
}
但是根据迪米特法则我们知道,对应类与类之间的关系,越少越好,如果我们的策略越多,那么上层业务逻辑需要知道的策略类也会随之增加,所以我们需要再次封装转移。
public class Context
{
private BaseStrategy baseStrategy;
public Context(string strategy)
{
switch (strategy)
{
case "步行":
this.baseStrategy = new StrategyWalk();
break;
case "轮船":
this.baseStrategy = new StrategyShip();
break;
case "火车":
this.baseStrategy = new StrategyTrain();
break;
case "飞机":
this.baseStrategy = new StrategyAirplane();
break;
default:
break;
}
}
public string GetResult(string side1,string side2)
{
return baseStrategy.GetRoute(side1, side2);
}
}
执行
void Start()
{
Context context = new Context("飞机");
string route = context.GetResult("地点一", "地点二");
Debug.Log(route);
}
这样上层只需要知道
Context
一个类就可以了,其他的都转移到下层执行。
3.7.5 写法对比:
略
3.7.6 模式分析:
根据定义的算法族可以使算法自由切换,扩展方便,但随着算法类的增多,
contenxt
中的算法也会逐渐增加,提高了出错的机率,届时需要对算法族再次封装(例:按类别),减少相互的干扰。
3.7.7 应用场景:
需要为一种行为提供不同的策略来达到获取不同结果的目的。
3.7.8 小结:
对于策略的选择是放到
Context
里面还是放到上层业务逻辑中需要根据实际情况自行权衡,但目的是一致的,就是减少类与类之间的依赖关系,降低其耦合度。而且在开发中可以将不同的算法以序列化的形式保存,例如ScriptableObjects,这样算法无需关心外部的环境而独立的保存。