.Net 设计模式进阶之路——策略模式[Strategy]

1,561 阅读3分钟

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战

  • 📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!
  • 📢本文作者:由webmote 原创,首发于 【掘金】
  • 📢作者格言: 生活在于折腾,当你不折腾生活时,生活就开始折腾你,让我们一起加油!💪💪💪

🎏 01.代理模式

意图: 定义一系列的算法,把这些算法设计为可被互相替换。

形象的说:虽然算法不同,但客户端的执行调用均不用修改,不同的算法就如同不同的策略一样,可以被随时替换。

image.png

问题领域:

  • 有许多不同的算法,不希望被硬编码到系统,
  • 算法可以按照情况互换,
  • 算法内的其他数据不希望暴露出去,
  • 旧系统重构,发现很多if分支的语句,可以考虑替换

解决方案: 我们使用UML图来描述它。

image.png

我们定义一个接口或抽象类Strategy,并设计其接口,由具体的实现类实现不同的算法,这里是ConcreteStrategy1和2类。

Client就是一个使用者,其内部可以实例化Strategy类,也可以按照条件进行配置不同的Strategy类,具体的应用方法通过接口或抽象类进行调用,而避免直接选定具体的类。

效果:

  • 好处:
  1. 可以扩算法系列;
  2. 可以替代直接继承的方案,避免把算法硬编码到使用类;
  3. 消除分支语句;
  4. 客户可以有多种选择;
  • 限定:
  1. 客户需要知道算法的不同点。
  2. 增加了对象数

🎏 02. dotnet core 源码赏析

aspnet Core源代码内有一个验证策略的接口IValidationStrategy,采用了策略模式。

public interface IValidationStrategy
    {       
        IEnumerator<ValidationEntry> GetChildren(ModelMetadata metadata, string key, object model);
    }
    internal class DefaultComplexObjectValidationStrategy : IValidationStrategy
    {

        public static readonly IValidationStrategy Instance = new DefaultComplexObjectValidationStrategy();

        private DefaultComplexObjectValidationStrategy()
        {
        }

        /// <inheritdoc />
        public IEnumerator<ValidationEntry> GetChildren(
            ModelMetadata metadata,
            string key,
            object model)
        {
            return new Enumerator(metadata, key, model);
        }

        
        }
  }

策略模式并不难理解,只要合适的场景就可以引入它。

🎏 03. dotnet 代理类实现

这是一个例子,我们来按照uml图的设计实现一个策略类,接口定义如下:

public abstract class Strategy
    {
        public abstract void AlgorithmInterface();
    }    
    public class ConcreteStrategyA : Strategy
    {
        public override void AlgorithmInterface()
        {
            Console.WriteLine(
                "Called ConcreteStrategyA.AlgorithmInterface()");
        }
    }   
    public class ConcreteStrategyB : Strategy
    {
        public override void AlgorithmInterface()
        {
            Console.WriteLine(
                "Called ConcreteStrategyB.AlgorithmInterface()");
        }
    }
    public class Client
    {
        Strategy strategy;
        // Constructor
        public Client(Strategy strategy)
        {
            this.strategy = strategy;
        }
        public void ContextInterface()
        {
            strategy.AlgorithmInterface();
        }
    }

调用方,可以按照下列方式直接使用。

Client context;
// Two contexts following different strategies
context = new Client(new ConcreteStrategyA());
context.ContextInterface();
context = new Client(new ConcreteStrategyB());
context.ContextInterface();

是的,通过上述的策略类,我们可以在客户端代码内,随意切换策略实现类,实现互换的目的,当然如果引入配置信息,还可以做到根据配置信息动态修改算法的功能。

你的项目内有无类似的场景,可以拿来练练手哦。

🎏 04. 小结

策略模式侧重于通过不同的算法达到相同的目的,关注点主要在对行为的抽象上,所以策略模式一般都是基于接口的。

每篇的设计模式,都是看起来容易,往往写起来很费力气,这可能是我在编程中大部分场景并没有使用到他们,或者使用的比较少的缘故吧,甚至于没有排在前面写的模式,可能都从来没用过呢。

当然查找.net源码,试图从里面找到我们需要的设计模式也不是个轻松的活。

虽然设计模式已经有很多文章了,但我还是希望能写的不同,一方面增强自己的记忆,一方面也给.net 广大程序员打打气,看看支撑我们的.net core源码里有多少设计模式可供我们学习。

所以能翻看源码的程序员不会差到哪里去!😳

例行小结,理性看待!

结的是啥啊,结的是我想你点赞而不可得的寂寞。😳😳😳

👓都看到这了,还在乎点个赞吗?

👓都点赞了,还在乎一个收藏吗?

👓都收藏了,还在乎一个评论吗?