本篇内容为博主个人在学习《大话设计模式》(程杰 著)过程中的测试随笔,在此给各位编程新手作为学习参考,毕竟网上深入学习的资料对于瓶颈期的新人大多不太友好,我会尽量详细的展示并解释每一个细节,也欢迎大家对我的不足给予批评指正。
这周一直在加班,今天终于早点下班了,继续把上周学习的内容记录一下。
本篇以商场收银软件应对多变的折扣策略为例,为我们展示如何把变化的算法封装起来,让它与业务隔离,同时减小程序的耦合度,让算法的变化不会影响到使用算法的客户。
项目目录如下
一、运算业务基类
结算业务类基类(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框架中可用于实现封装不同类型数据库的增删改查方法等,目前对这个算法的理解还是不太透彻,希望以后遇到实际需求时,能够用得上它。