• 设计模式(二十二)—— 策略模式


    模式简介


    定义一系列的算法,把它们一个个封装起来,并且使它们可互相替换。本模式使得算法可独立于使用它的客户而变化。

    策略模式也被称为政策模式,它是一种行为型模式。为了完成某一项任务,往往可以有很多种不同的方式,例如商场促销,有不同的促销手段,比如提价50满100减20、原价两倍打八折等等,这每一种方式我们称之为策略。为了避免将策略硬编码在程序当中,可以使用策略模式,在系统运行过程中根据具体的环境或者条件执行不同的策略。

    结构分析


    UML类图

    角色说明

    • Context

    上下文类。包含一个对Strategy对象的引用,提供一个方法配置ConcreteStrategy对象,实现算法的动态替换。

    • Strategy

    策略接口。定义算法的公共接口,Context类通过这个接口调用具体策略的算法。

    • ConcreteStrategy

    具体策略。实现策略接口,定义具体算法。

    工作原理

    Context类提供一个方法(SetStrategy)设置具体算法,并将该对象的引用保存到私有变量_strategy中。Context将客户端请求转发给_strategy对象,完成策略调用。

    结构代码

    //策略接口
    interface IStrategy
    {
        void AlgorithmInterface();
    }
    
    //上下文类
    class Context
    {
        private IStrategy _strategy;
        public void SetStrategy(IStrategy strategy)
        {
            _strategy = strategy;
        }
        public void ContextInterface()
        {
            _strategy.AlgorithmInterface();
        }
    }
    
    //具体策略A
    class ConcreteStrategyA : IStrategy
    {
        public void AlgorithmInterface()
        {
            Console.WriteLine("Called ConcreteStrategyA.AlgorithmInterface()");
        }
    }
    
    //具体策略B
    class ConcreteStrategyB : IStrategy
    {
        public void AlgorithmInterface()
        {
            Console.WriteLine("Called ConcreteStrategyB.AlgorithmInterface()");
        }
    }
    
    //客户端调用
    class Program
    {
        static void Main(string[] args)
        {
            Context context = new Context();
            context.SetStrategy(new ConcreteStrategyA());
            context.ContextInterface();
            context.SetStrategy(new ConcreteStrategyB());
            context.ContextInterface();
            Console.ReadLine();
        }
    }
    

    程序输出:

    示例分析


    本节我们依然实现文章开头中的示例,首先声明ISalesPromotion接口。

    public interface ISalesPromotion
    {
        void Calculate(int orgPrice);
    }
    

    分别实现提价50满100减20以及原价两倍打八折两种销售策略。

    public class Reduction : ISalesPromotion
    {
        public void Calculate(int orgPrice)
        {
            var price = orgPrice + 50 - 20;
            Console.WriteLine($"Original Price : [{orgPrice}] , Price : [{price}]");
        }
    }
    
    public class Discount : ISalesPromotion
    {
        public void Calculate(int orgPrice)
        {
            var price = orgPrice * 2 * 0.8;
            Console.WriteLine($"Original Price : [{orgPrice}] , Price : [{price}]");
        }
    }
    

    创建产品类

    public class Product
    {
        private ISalesPromotion _promotion;
        public void SetPromotion(ISalesPromotion promotion)
        {
            _promotion = promotion;
        }
        public void PrintPrice(int price)
        {
            _promotion.Calculate(price);
        }
    }
    

    客户端调用

    class Program
    {
        static void Main(string[] args)
        {
            int price1 = 120;
            Product p1 = new Product();
            //设置促销策略为满减
            p1.SetPromotion(new Reduction());
            p1.PrintPrice(price1);
    
            int price2 = 500;
            Product p2 = new Product();
            //设置促销策略为打折
            p2.SetPromotion(new Discount());
            p2.PrintPrice(price2);
    
            Console.ReadLine();
        }
    }
    

    程序输出

    使用场景


    • 许多相关的类仅仅时行为上有差异。策略模式可以动态地让一个对象在众多行为中选择一种行为。

    • 一个系统需要动态地在几种算法中选择一种。

    • 一个对象有很多行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。

    • 不希望客户知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性及安全性。

  • 相关阅读:
    OAuth2.0系列之授权码模式实践教程(二)
    OAuth2.0系列之基本概念和运作流程(一)
    OAuth2.0系列之单点登录SSO实现
    Mybatis系列之设置自动提交事务
    springMVC系列之@Responsebody接口弹出f.txt下载问题
    Oracle应用之批量递增更新数据脚本
    前端 自定义弹出框-提示框(一)
    IE不兼容问题 字符串格式化
    JS 打开本地应用软件
    PPT导出为图片
  • 原文地址:https://www.cnblogs.com/Answer-Geng/p/9356301.html
Copyright © 2020-2023  润新知