zoukankan      html  css  js  c++  java
  • 设计模式(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对象会随着策略对象的改变而变更其执行算法。

    策略模式的优点

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

    策略模式的缺点

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

    策略模式的适用场景

    • 多个类只有在算法或行为上稍有不同的场景。
    • 算法需要自由切换的场景。
  • 相关阅读:
    Codeforces 834D The Bakery
    hdu 1394 Minimum Inversion Number
    Codeforces 837E Vasya's Function
    Codeforces 837D Round Subset
    Codeforces 825E Minimal Labels
    Codeforces 437D The Child and Zoo
    Codeforces 822D My pretty girl Noora
    Codeforces 799D Field expansion
    Codeforces 438D The Child and Sequence
    Codeforces Round #427 (Div. 2) Problem D Palindromic characteristics (Codeforces 835D)
  • 原文地址:https://www.cnblogs.com/zhixin9001/p/13697537.html
Copyright © 2011-2022 走看看