美文网首页
策略模式

策略模式

作者: 周末的游戏之旅 | 来源:发表于2019-08-29 17:47 被阅读0次

在讲策略模式之前,我们先看一个日常生活中的小例子:
  现实生活中我们到商场买东西的时候,卖场往往根据不同的客户制定不同的报价策略,比如针对新客户不打折扣,针对老客户打9折,针对VIP客户打8折...
  现在我们要做一个报价管理的模块,简要点就是要针对不同的客户,提供不同的折扣报价。
如果是有你来做,你会怎么做?如果没有策略模式,可能会用大量的if-else if 或者switch,再或者是将每个计算方法封装到相应的方法中去调用。
但是这样的代码会有很多问题:

1.当我们新增一个客户类型的时候,首先要添加一个该种客户类型的报价算法方法,然后再quote方法中再加一个else if的分支,是不是感觉很是麻烦呢?而且这也违反了设计原则之一的开闭原则(open-closed-principle).

开闭原则:
对于扩展是开放的(Open forextension)。这意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。也就是说,我们可以改变模块的功能。
对于修改是关闭的(Closed for modification)。对模块行为进行扩展时,不必改动模块的源代码或者二进制代码。

2.我们经常会面临这样的情况,不同的时期使用不同的报价规则,比如在各个节假日举行的各种促销活动时、商场店庆时往往都有普遍的折扣,但是促销时间一旦过去,报价就要回到正常价格上来。按照上面的代码我们就得修改if else里面的代码很是麻烦

定义:

策略模式定义了一些列的算法,并将每一个算法封装起来,使每个算法可以互相替代,使算法本身的和使用算法的客户端分割开来,相互独立。

UML图

UML序列图

实现

针对我们一开始讲的报价管理的例子:我们可以应用策略模式对其进行改造,不同类型的客户有不同的折扣,我们可以将不同类型的客户的报价规则都封装为一个独立的算法,然后抽象出这些报价算法的公共接口

报价策略接口:

/// <summary>
/// 报价策略接口
/// </summary>
interface IQuoteStrategy
{
    float GetPrice(float originalPrice);
}

新客户报价策略实现:

/// <summary>
/// 新用户报价策略
/// </summary>
class NewCustomQuoteStrategy : IQuoteStrategy
{
    public float GetPrice(float originalPrice)
    {
        Console.WriteLine("抱歉,新用户没有折扣");
        return originalPrice;
    }
}

老客户报价策略实现:

/// <summary>
/// 老客户报价策略
/// </summary>
class OldCustomQuoteStrategy : IQuoteStrategy
{
    public float GetPrice(float originalPrice)
    {
        Console.WriteLine("老用户9折");
        return originalPrice * 0.9f;
    }
}

VIP客户报价实现:

/// <summary>
/// VIP客户报价策略
/// </summary>
class VIPCustomStrategy : IQuoteStrategy
{
    public float GetPrice(float originalPrice)
    {
        Console.WriteLine("VIP客户8折");
        return originalPrice * 0.8f;
    }
}

报价上下文

/// <summary>
/// 报价上下文
/// </summary>
class QuoteContext
{
    private IQuoteStrategy strategy;

    /// <summary>
    /// 注入报价策略
    /// </summary>
    /// <param name="strategy"></param>
    public QuoteContext(IQuoteStrategy strategy)
    {
        this.strategy = strategy;
    }

    /// <summary>
    /// 回调具体报价策略方法
    /// </summary>
    /// <param name="originalPrice"></param>
    /// <returns></returns>
    public float GetPrice(float originalPrice)
    {
        return strategy.GetPrice(originalPrice);
    }
}

外部客户端

/// <summary>
/// 外部客户端
/// </summary>
class Program
{
    static void Main(string[] args)
    {
        //1.创建老用户的报价策略
        IQuoteStrategy oldQuoteStrategy = new OldCustomQuoteStrategy();

        //2.创建报价上下文对象,并设置具体的报价策略
        QuoteContext quoteContext = new QuoteContext(oldQuoteStrategy);

        //3.调用报价上下文的方法
        float price = quoteContext.GetPrice(100);

        Console.WriteLine(price);
    }
}

这个时候,商场营销部新推出了一个客户类型--MVP用户(Most Valuable Person),可以享受折扣7折优惠,那该怎么办呢?

这个很容易,只要新增一个报价策略的实现,然后外部客户端调用的时候,创建这个新增的报价策略实现,并设置到策略上下文就可以了,对原来已经实现的代码没有任何的改动。

/// <summary>
/// MVP客户报价策略
/// </summary>
class MVPCustomStrategy : IQuoteStrategy
{
    public float GetPrice(float orginalPrice)
    {
        Console.WriteLine("MVP客户7折");
        return orginalPrice * 0.7f;
    }
}
/// <summary>
/// 外部客户端
/// </summary>
class Program
{
    static void Main(string[] args)
    {
        //1.创建MVP用户的报价策略
        IQuoteStrategy oldQuoteStrategy = new MVPCustomStrategy();

        //2.创建报价上下文对象,并设置具体的报价策略
        QuoteContext quoteContext = new QuoteContext(oldQuoteStrategy);

        //3.调用报价上下文的方法
        float price = quoteContext.GetPrice(100);

        Console.WriteLine(price);
    }
}

深入理解策略模式

策略模式的作用

就是把具体的算法实现从业务逻辑中剥离出来,成为一系列独立算法类,使得它们可以相互替换。

策略模式的着重点

不是如何实现算法,而是如果组织和调用这些算法,从而让我们的程序结构更加的灵活、可扩展。
策略模式就是把各个平等的具体实现进行抽象、封装成为独立的算法类,然后通过上下文和具体的算法类来进行交互。各个策略算法都是平等的,地位是一样的,正是由于各个算法的平等性,所以它们才是可以相互替换的。虽然我们可以动态切换各个策略,但是同一时刻只能使用一个策略。

参考:https://www.cnblogs.com/lewis0077/p/5133812.html

相关文章

网友评论

      本文标题:策略模式

      本文链接:https://www.haomeiwen.com/subject/ajhwectx.html