• 设计模式(22) 策略模式


    在策略模式中,一个类的行为或算法可以在运行时动态更改。

    GOF对策略模式的描述为:
    Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients.
    — Design Patterns : Elements of Reusable Object-Oriented Software

    UML类图如下:

    策略模式包含三个角色:

    • Context上下文角色,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。
    • Strategy抽象策略角色,策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。
    • ConcreteStrategy具体策略角色,实现抽象策略中的操作,该类含有具体的算法。

    代码示例:
    以电商会员折扣为例,不同级别的会员享受的折扣是不同的,这种差异可以用策略模式来封装。

    public interface Strategy
    {
        double CalcPrice(double originalPrice);
    }
    
    public class PrimaryStrategy : Strategy
    {
        public double CalcPrice(double originalPrice)
        {
            return originalPrice;
        }
    }
    
    public class IntermediateStrategy : Strategy
    {
        public double CalcPrice(double originalPrice)
        {
            return originalPrice * 0.9;
        }
    }
    public class AdvancedStrategy : Strategy
    {
        public double CalcPrice(double originalPrice)
        {
            return originalPrice * 0.8;
        }
    }
    
    public class PriceContext
    {
        public Strategy Strategy { get; set; }
    
        public double GetPrice(double originalPrice)
        {
            return this.Strategy.CalcPrice(originalPrice);
        }
    }
    

    调用端:

    public class Test
    {
        public static void Entry()
        {
            Strategy strategy = new PrimaryStrategy();
            PriceContext price = new PriceContext();
            price.Strategy = strategy;
    
            Console.WriteLine(price.GetPrice(100)); //100
    
            strategy = new IntermediateStrategy();
            price.Strategy = strategy;
            Console.WriteLine(price.GetPrice(100)); //90
    
            strategy = new AdvancedStrategy();
            price.Strategy = strategy;
            Console.WriteLine(price.GetPrice(100)); //80
        }
    }
    

    示例中有若干具体的策略类,以及一个context对象,context对象会随着策略对象的改变而变更其执行算法。

    策略模式的优点

    • 算法可以自由切换,只要实现抽象策略,它就成为策略家族的一个成员,通过封装角色对其进行封装,保证对外提供“可自由切换”的策略。
    • 避免使用多重条件判断,多重条件语句不易维护,而且出错的概率较大。使用策略模式后,可以由其他模块决定采用何种策略,策略家族对外提供的访问接口就是封装类,简化了操作,同时避免了条件语句判断。
    • 扩展性良好,在现有的系统中增加一个策略非常容易,只要实现接口就可以了。

    策略模式的缺点

    • 策略类数量增多,每一个策略都是一个类,复用的可能性很小,类数量增多。
    • 所有的策略类都需要对外暴露,上层模块必须知道有哪些策略,并了解这些策略之间的区别,然后才能决定使用哪一个策略,这与迪米特法则是相违背的。

    策略模式的适用场景

    • 多个类只有在算法或行为上稍有不同的场景。
    • 算法需要自由切换的场景。
  • 相关阅读:
    小程序路由
    机器学习笔记—支持向量机(1)
    用极大似然估计法推出朴素贝叶斯法中的先验概率估计公式
    机器学习笔记—生成学习
    机器学习笔记—再谈广义线性模型
    机器学习笔记—指数分布簇和广义线性模型
    机器学习笔记—Logistic 回归
    机器学习笔记—局部权重线性回归
    机器学习笔记—线性回归
    机器学习笔记1
  • 原文地址:https://www.cnblogs.com/zhixin9001/p/13697537.html
Copyright © 2020-2023  润新知