• 行为型模式之策略模式


    概述

    在策略模式中,我们可以定义一些独立的类来封装不同的算法,每一个类封装一种具体的算法,在这里,每一个封装算法的类我们都可以称之为一种策略(Strategy),为了保证这些策略在使用时具有一致性,一般会提供一个抽象的策略类来做规则的定义,而每种算法则对应于一个具体策略类。

    策略模式的主要目的是将算法的定义与使用分开,也就是将算法的行为和环境分开,将算法的定义放在专门的策略类中,每一个策略类封装了一种实现算法,使用算法的环境类针对抽象策略类进行编程,符合“依赖倒转原则”。在出现新的算法时,只需要增加一个新的实现了抽象策略类的具体策略类即可

    定义

    策略模式(Strategy Pattern):定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。策略模式是一种对象行为型模式。

    实现

    洗发水商品

        /// <summary>
        /// 洗发水
        /// </summary>
        class LiquidShampoo
        {
            public double Price { get; set; }
    
            public int Num { get; set; }
    
            /// <summary>
            /// 促销方法
            /// </summary>
            /// <param name="discount">促销方案</param>
            /// <returns></returns>
            public double Promotion(Discount discount)
            {
                Console.WriteLine("洗发水数量:{0},单价:{1}", this.Num, this.Price);
                //调用折扣类的折扣价计算方法
                return discount.Calculate(this.Price, this.Num);
            }
        }

    促销策略

        /// <summary>
        /// 折扣类:抽象策略类
        /// </summary>
        interface Discount
        {
            /// <summary>
            /// 打折方法
            /// </summary>
            /// <param name="originalPrice">原价</param>
            /// <param name="num">数量</param>
            /// <returns>折后总价</returns>
            double Calculate(double originalPrice, int num);
        }
        /// <summary>
        /// 5折优惠
        /// </summary>
        class Discount_0_5 : Discount
        {
            public double Calculate(double originalPrice, int num)
            {
                Console.WriteLine("促销方案:5折优惠!");
                var disPrice = num * originalPrice * 0.5;
                Console.WriteLine("总价:{0}", disPrice);
                return disPrice;
            }
        }
        /// <summary>
        /// 买3送2
        /// </summary>
        class Discount_3_Buy_2 : Discount
        {
            public double Calculate(double originalPrice, int num)
            {
                Console.WriteLine("促销方案:买3送2!");
                var disPrice = num * originalPrice;
                Console.WriteLine("总价:{0}", disPrice);
                return disPrice;
            }
        }
        /// <summary>
        /// 满减
        /// </summary>
        class Discount_Reach100_Deduction20 : Discount
        {
            public double Calculate(double originalPrice, int num)
            {
                Console.WriteLine("满100减20!");
                var disPrice = num * originalPrice;
                disPrice = disPrice >= 100 ? disPrice - 20 : disPrice;
                Console.WriteLine("总价:{0}", disPrice);
                return disPrice;
            }
        }

    客户端

        class Program
        {
            static void Main(string[] args)
            {
                //洗发水商品
                LiquidShampoo ls = new LiquidShampoo() { Price = 33, Num = 5 };
                //采用5折优惠
                ls.Promotion(new Discount_0_5());
                //买3送2
                ls.Promotion(new Discount_3_Buy_2());
                //满百减20
                ls.Promotion(new Discount_Reach100_Deduction20());
                Console.ReadLine();
            }
        }

    结果

    总结

     主要优点

    1、策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。

    2、 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族,恰当使用继承可以把公共的代码移到抽象策略类中,从而避免重复的代码。

    3、 策略模式提供了一种可以替换继承关系的办法。如果不使用策略模式,那么使用算法的环境类就可能会有一些子类,每一个子类提供一种不同的算法。但是,这样一来算法的使用就和算法本身混在一起,不符合“单一职责原则”,决定使用哪一种算法的逻辑和该算法本身混合在一起,从而不可能再独立演化;而且使用继承无法实现算法或行为在程序运行时的动态切换。

    4、 使用策略模式可以避免多重条件选择语句。多重条件选择语句不易维护,它把采取哪一种算法或行为的逻辑与算法或行为本身的实现逻辑混合在一起,将它们全部硬编码(Hard Coding)在一个庞大的多重条件选择语句中,比直接继承环境类的办法还要原始和落后。

    5、 策略模式提供了一种算法的复用机制,由于将算法单独提取出来封装在策略类中,因此不同的环境类可以方便地复用这些策略类。

    主要缺点

    1、 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。

    2、 策略模式将造成系统产生很多具体策略类,任何细小的变化都将导致系统要增加一个新的具体策略类。

    3、 无法同时在客户端使用多个策略类,也就是说,在使用策略模式时,客户端每次只能使用一个策略类,不支持使用一个策略类完成部分功能后再使用另一个策略类来完成剩余功能的情况。

  • 相关阅读:
    互评
    201671010438 王奕晗英文文本词频统计
    201671010438王奕晗 实验二词频统计
    201671010438王奕晗 实验三 作业互评与改进
    通读《构建之法》所提出的问题
    个人学习总结博客(201671010440 王雨竹)
    互评
    201671010440王雨竹+《英文文本统计分析》
    201671010440 王雨竹 词频统计软件项目报告
    201671010440 王雨竹 实验三 作业互评与改进
  • 原文地址:https://www.cnblogs.com/Jabben_Yi/p/5634958.html
Copyright © 2020-2023  润新知