大话设计模式笔记——策略模式

本篇内容为博主个人在学习《大话设计模式》(程杰 著)过程中的测试随笔,在此给各位编程新手作为学习参考,毕竟网上深入学习的资料对于瓶颈期的新人大多不太友好,我会尽量详细的展示并解释每一个细节,也欢迎大家对我的不足给予批评指正。

这周一直在加班,今天终于早点下班了,继续把上周学习的内容记录一下。

本篇以商场收银软件应对多变的折扣策略为例,为我们展示如何把变化的算法封装起来,让它与业务隔离,同时减小程序的耦合度,让算法的变化不会影响到使用算法的客户。

项目目录如下

在这里插入图片描述

一、运算业务基类

结算业务类基类(BaseCharge)定义了一个计算金额的虚方法(CountMoney())。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StrategyTest.Business
{
    class BaseCharge
    {
       /// <summary>
       /// 计算金额
       /// </summary>
       /// <param name="TotalPrice">应收款</param>
       /// <returns>实收款</returns>
        public virtual double CountMoney(double TotalPrice)
        {
            return TotalPrice;
        }
    }
}

二、按折扣计算金额算法类

继承结算业务类基类(BaseCharge),重写基类方法CountMoney(),实现对应收款的打折后实付款算法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StrategyTest.Business
{
    class ChargeByDiscount : BaseCharge
    {
        /// <summary>
        /// 折扣率
        /// </summary>
        private double DiscountRate;

        /// <summary>
        /// 构造函数,将传入的折扣率赋值
        /// </summary>
        /// <param name="discountRate">折扣率</param>
        public ChargeByDiscount(string discountRate)
        {
            DiscountRate = Convert.ToDouble(discountRate);
        }

        /// <summary>
        /// 重写基类计算价格的方法
        /// </summary>
        /// <param name="TotalPrice">应收款</param>
        /// <returns>实付款</returns>
        public override double CountMoney(double TotalPrice)
        {
            return TotalPrice * DiscountRate;
        }
    }
}

三、按满减计算金额算法类

继承结算业务类基类(BaseCharge),重写基类方法CountMoney(),实现对应收款的满减后实付款算法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StrategyTest.Business
{
    class ChargeByFullSub : BaseCharge
    {
        /// <summary>
        /// 条件金额
        /// </summary>
        public double ConditionalMoney = 0;
        /// <summary>
        /// 减免金额
        /// </summary>
        public double SubMoney = 0;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="conditionalMoney">条件金额</param>
        /// <param name="subMoney">减免金额</param>
        public ChargeByFullSub(double conditionalMoney, double subMoney)
        {
            ConditionalMoney = conditionalMoney;
            SubMoney = subMoney;
        }

        /// <summary>
        /// 重写基类计算价格的方法
        /// </summary>
        /// <param name="TotalPrice">应收款</param>
        /// <returns>实付款</returns>
        public override double CountMoney(double TotalPrice)
        {
            return TotalPrice - Math.Floor(TotalPrice / ConditionalMoney) * SubMoney;
        }
    }
}

四、按原价计算金额算法类

继承结算业务类基类(BaseCharge),重写基类方法CountMoney(),实现对应收款的原价计算实付款算法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StrategyTest.Business
{
    class ChargeByNormal : BaseCharge
    {
        /// <summary>
        /// 重写基类计算价格的方法
        /// </summary>
        /// <param name="TotalPrice">应收款</param>
        /// <returns>实付款</returns>
        public override double CountMoney(double TotalPrice)
        {
            return TotalPrice;
        }
    }
}

五、Context上下文

定义一个算法实例oCharge ,通过简单工厂模式获取相应的算法类实例,调用各个算法类重写的基类计算金额方法来计算应付款。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StrategyTest.Business
{
    class ChargeContext
    {
        /// <summary>
        /// 定义一个算法实例
        /// </summary>
        BaseCharge oCharge = null;

        /// <summary>
        /// 构造函数,同时利用简单工厂模式,获取对应的计算类实例
        /// </summary>
        /// <param name="CountType">计算类型字符串</param>
        public ChargeContext(string CountType)
        {
            switch (CountType)
            {
                case "正常收费":
                    this.oCharge = new ChargeByNormal();
                    break;
                case "打八折":
                    this.oCharge = new ChargeByDiscount("0.8");
                    break;
                case "满400减50":
                    this.oCharge = new ChargeByFullSub(400, 50);
                    break;
            }
        }

        /// <summary>
        /// 获取最终实付款金额
        /// </summary>
        /// <param name="TatolPrices">应收款</param>
        /// <returns>实付款</returns>
        public double GetResultPrices(double TatolPrices)
        {
            return oCharge.CountMoney(TatolPrices);
        }

    }
}

六、WinFrom后台代码

WinFrom界面如下
在这里插入图片描述

WinFrom后台代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using StrategyTest.Business;

namespace StrategyTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btn_Count_Click(object sender, EventArgs e)
        {
            double oTotalPrices = 0;

            //简单工厂写法
            //BaseCharge oCharge = ChargeContext.InstantiationCharge(cmb_CountType.SelectedItem.ToString());
            //oTotalPrices = oCharge.CountMoney(Convert.ToDouble(txt_UnitPrice.Text.Trim()) * Convert.ToDouble(txt_Num.Text.Trim()));

            //策略加简单工厂写法

            ChargeContext oChargeContext = new ChargeContext(cmb_CountType.SelectedItem.ToString());
            oTotalPrices = oChargeContext.GetResultPrices(Convert.ToDouble(txt_UnitPrice.Text.Trim()) * Convert.ToDouble(txt_Num.Text.Trim()));
            lab_Total.Text = oTotalPrices.ToString();
        }
    }
}

个人理解策略模式主要用来封装各种业务规则,比如ORM框架中可用于实现封装不同类型数据库的增删改查方法等,目前对这个算法的理解还是不太透彻,希望以后遇到实际需求时,能够用得上它。

猜你喜欢

转载自blog.csdn.net/xzw18287443015/article/details/83626073
今日推荐