c#策略模式
1.定义:
定义一组算法,将每个算法封装起来,并使它们可以互相替换。
策略模式让算法的变化独立于使用它的客户端。
是一种 行为型设计模式:涉及到对象之间如何通信和交互
2.一个普通的例子

想从A点到达B点,有两种方案:
-
方案一:低速路,全程限速60
-
方案二:高速路,全程限速100,但是需要收费
现在我们在高德地图中,可以让用户选是哪种路线,然后进行导航。
用户选择低速路,我们在高德地图中有对应的低速导航算法;如果用户选择高速路,在高德地图中有对应的高速导航算法。
我们会根据配置,在运行时调用特定的计算逻辑。
策略设计模式的本质:如何设计软件,以便你可以轻松替换底层算法,而不会影响周围的代码。无论我们使用最快路线,最短路线,避开收费路段,还是其他100种不同的算法,周围的代码都可以保持不变。我们可以透明的替换底层算法。
再次回顾 策略模式 的定义
-
定义一组算法:用于计算或执行某些操作的不同算法
-
将每个算法封装起来:可以将其想象为一个类,一个方法,一个组件,或者一个子系统,你将它封装在某种可互换的结构中。
-
并使它们可以互相替换: 可互换,本质上是指让它们暴露相同的接口。如果它们暴露相同的接口,客户端就可以使用该接口。而在幕后,我们可以替换底层的组件。
策略模式赋予我们的能力是:让算法可以独立且透明地变化,而不影响使用它的客户端。客户端完全使用相同的代码,它使用的是某个接口,但是在幕后,我们替换了底层的算法。
策略模式的另一种解释:
-
将可互换的逻辑置于接口之后
3.策略模式的类图

-
有一个名为策略strategy的接口,策略指的就是算法,这个接口就是为该算法定义的。
-
我们在接口中,放一个名为execute()的方法,表示一种算法。
-
-
有几个具体的策略,它们是strategy接口的具体实现,是具体的算法本身,它们可以互相替换。
-
有一个上下文Context,上下文内部私有地持有一个策略,并提供两个方法,
-
一个方法是SetStrategy(),它接收一个策略
-
另一个方法是 ExecuteStrategy(),它执行底层的策略
-
3.1高德地图的具体实例:

-
接口Strategy:在高德地图中,它是一个GetRoute()方法,用于获取具体的道路算法。
-
具体策略:实现了接口Strategy的具体算法
-
ConcreteStrategyA:避开收费路线算法
-
ConcreteStrategyB:获取最快路线
-
ConcreteStrategyC:获取最短路线
-
一组算法家族,它们都被隐藏在统一的接口之后
-
-
上下文Context:执行策略的组件
-
strategy:策略接口,在运行时它会是具体策略算法中的某一个
-
ExecuteStrategy()方法:Navigate()方法,用于导航,无论底层组件是哪一个,这个方法都会保持完全不变
-
SetStrategy()方法:可以设置具体的算法。
-
4.代码示例():
public interface IStrategy
{
void Execute();
}
public class ConcreteStrategyA:IStrategy
{
public void Execute()
{
Console.WriteLine("执行了策略A");
}
}
public class ConcreteStrategyB:IStrategy
{
public void Execute()
{
Console.WriteLine("执行了策略B");
}
}
public class ConcreteStrategyC:IStrategy
{
public void Execute()
{
Console.WriteLine("执行了策略C");
}
}
public class Context
{
private IStrategy? _strategy;
public void SetStrategy(IStrategy strategy)
{
_strategy = strategy;
}
public void ExecuteStragegy()
{
_strategy?.Execute();//仅在_strategy不为null时,才执行
}
}
//调用实例:
Context context = new();
context.SetStrategy(new ConcreteStrategyA());//注入策略A
context.ExecuteStrategy();
context.SetStrategy(new ConcreteStrategyC());//注入策略C
context.ExecuteStrategy();
//输出结果
执行了策略A
执行了策略C
//从客户端的角度看,它只是调用了ExecuteStrategy(),但我们在运行的时候,替换了底层的具体策略。
5.支付处理的实例:

-
购物车包含一个Checkout方法用于付款,我们在Checkout中计算金额,然后会使用支付策略。
-
在运行时,支付策略可以是,信用卡支付,PayPal支付,银行转账具体策略中的某一种。
-
根据我们持有的—IPaymentStrategy接口,我们可以使用某种具体的支付策略完成支付。
-
每种策略可以完全不同,可以拥有不同的参数,内部行为也可以不同,所有内容都隐藏在完全相同的接口背后
6.策略模式的优缺点:
-
优点:
-
可扩展性:一旦我们定义了策略接口,并且客户端通过该接口工作,我们就可以非常轻松地扩展具体策略的数量,想创建多少就创建多少。上下文并不关心它使用的是哪一个具体策略,只要这个策略实现了接口即可。
-
灵活性:我们可以轻松替换底层的具体策略,而无需修改客户端的任何代码。这种替换不仅可以在加载配置时发生,也可以在运行时动态变化。
-
关注点分离:每个策略都封装了与其相关的特定逻辑,特定算法,每种算法都只负责自己特定的部分。
-
-
缺点:
-
导致类的数量增加:简单的算法分支完全可以使用ifelse或者switch分支,而不必创建大量类,策略算法越复杂,使用策略设计模式的效益越高。
-
如果处理的是一个简单的用例,并且底层算法并不复杂,那么使用这个策略模式,反而会增加复杂度。
-
不同算法之间共享数据变得复杂。
-
更多推荐
所有评论(0)