- 携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情
前言
什么是策略模式?
它定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化不会影响到使用算法的客户。
如何理解策略模式?
用业务理解设计
问题
某大型超市由于竞争压力过大,为提升销售额,促进客户消费,特使用全场满100-10优惠,针对这种场景显然用代码实现起来也非常容易。
为了满足用户多样化的需求,新增了折扣全场8折优惠制度,这个时候为了保留原先逻辑,在优惠规则关键类上继续进行逻辑开发,由于需求变化,还得要在关键类上继续迭代修改,代码越来越臃肿,里面逻辑也越来越复杂,导致维护起来变得异常困难,如果不同收费由不同人维护,还会导致代码冲突频繁,很显然这样的设计不是最优的。
引入策略模式
通过前言了解到策略模式,我们不难看出,他的概念恰恰就非常合适目前场景,存在许多不同方式完成特定收费的类,并且可以自由的替换,每一种优惠就相当于一个策略。
策略模式结构
- 策略 (Strategy):是所有具体策略的通用接口, 它声明了一个上下文用于执行策略的方法。
- 具体策略 (Concrete Strategies):实现了上下文所用算法的各种不同变体。
- 上下文(Context):指向具体策略的引用
代码实现
- 创建优惠策略接口IPreferential 定义计算优惠方法 CalcPreferential(double money)
public interface IPreferential
{
void CalcPreferential(double money);
}
- 创建具体策略(StrategyA:满减,StrategyB:折扣),也就是计算优惠方式的各种算法实现
public class StrategyA : IPreferential
{
public void CalcPreferential(double money)
{
Console.WriteLine("满减100-10");
}
}
public class StrategyB : IPreferential
{
public void CalcPreferential(double money)
{
Console.WriteLine("打8折");
}
}
- 新增上下文,创建上下文PreferentialContext类通过策略接口与所有策略交互
public class PreferentialContext
{
public IPreferential _preferential { get; set; }
//通过构造函数接受策略对象
public PreferentialContext(IPreferential preferential)
{
_preferential = preferential;
}
public void executeStrategy(double money)
{
_preferential.CalcPreferential(money);
}
}
- 客户端执行
static void Main(string[] args)
{
PreferentialContext preferential = new PreferentialContext(new StrategyA());
preferential.executeStrategy(0.1);
}
总结
策略模式优缺点
优点
- 引入新策略,无需修改原有代码
- 各个算法都有自己的类,对于测试、维护非常友好,并且也减少了if else这类条件语句
- 算法之间自由切换
缺点
- 从上述代码可以看出,客户端调用是需要知道具体策略的不同,进行选择合适的策略。换句话说就是客户端知道具体策略才适合使用策略模式
- 策略模式会将每个具体策略封装成类,会造成系统中存在大量的对象。
应用场景
- 当你有执行某些行为(如优惠活动)时略有不同的相似类时
- 如希望在系统中使用多种算法,并且希望能自由切换他们
. . . . . . . . . .