读《大话设计模式》——应用策略模式的"商场收银系统"(WinForm)
2020-12-29 09:35
标签:break 查询 nbsp center 显示 区别 new 生成 art 策略模式的结构
这个模式涉及到三个角色: 环境(Context)角色:持有一个 Strategy 类的引用。 上篇博文写的CashSuper 就是抽象策略,而正常收费 CashNormal、打折收费 CashRebate 和返利收费 CashReturn 就是三个具体策略,也就是策略模式中说的具体算法。 附上上篇博文的部分代码 加入的策略模式(这里可以弃用工厂模式了) 但是程序还是少不了switch...case语句, 核心代码(v1.3) 最初的策略模式是有缺点的,客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户 去掉switch...case语句!!!——(本案例采用简单的.net技术:反射) 关键的操作代码为:Assembly.Load(" 程序集名称").CreateInstance(" 名称空间.类名称"); 客户端代码(v1.4) 通过程序去读XML的配置文件,来生成这个下拉列表框,然后再根据用户的选择,通过反射实时的实例化出相应的算法对象,最终利用策略模式计算最终的结果。 XML文件——CashAcceptType.xml代码如下 现在无论需求是什么,用现在的程序,只需要改改XML文件就全部摆平了。比如现在老板觉得现在满300送100太多了,要改成送80,我只需要去XML文件里改就行了。 注:如要添加新的算法,那么该算法类继承CashSuper,再去改一下XML文件就可以了。 读《大话设计模式》——应用策略模式的"商场收银系统"(WinForm) 标签:break 查询 nbsp center 显示 区别 new 生成 art 原文地址:https://www.cnblogs.com/gltks/p/13284725.html
抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。//正常消费,继承CashSuper
class CashNormal:CashSuper
{
public override double acceptCash(double money)
{
return money;
}
}
//打折收费消费,继承CashSuper
class CashRebate:CashSuper
{
private double moneyRebate = 1d;
//初始化时,必需要输入折扣率,如八折,就是0,8
public CashRebate(string moneyRebate)
{
//界面向类传值
this.moneyRebate = double.Parse(moneyRebate);
}
public override double acceptCash(double money)
{
return money * moneyRebate;
}
}
//返利收费
class CashReturn:CashSuper
{
private double moneyCondition = 0.0d;
private double moneyReturn = 0.0d;
//初始化时必须要输入返利条件和返利值,比如满300返100
//则moneyCondition为300,moneyReturn为100
public CashReturn(string moneyCondition, string moneyReturn)
{
this.moneyCondition =double.Parse(moneyCondition);
this.moneyReturn = double.Parse(moneyReturn);
}
public override double acceptCash(double money)
{
double result = money;
//若大于返利条件,则需要减去返利值
if (money >= moneyCondition)
{
result = money - Math.Floor(money / moneyCondition) * moneyReturn;
}
return result;
}
}
//现金收取父类
abstract class CashSuper
{
//抽象方法:收取现金,参数为原价,返回为当前价
public abstract double acceptCash(double money);
}
1 namespace ExtendDiscountOfStrategyPattern
2 {
3 class CashContext
4 {
5 //声明一个现金收费父类对象
6 private CashSuper cs;
7
8 //设置策略行为,参数为具体的现金收费子类(正常,打折或返利)
9 public void setBehavior(CashSuper csuper)
10 {
11 this.cs = csuper;
12 }
13
14 //得到现金促销计算结果(利用了多态机制,不同的策略行为导致不同的结果)
15 public double GetResult(double money)
16 {
17 return cs.acceptCash(money);
18 }
19 }
20 }
1 //声明一个double变量total来计算总计
2 double total = 0.0d;
3 private void btnConfirm_Click(object sender, EventArgs e)
4 {
5 //声明一个double变量totalPrices
6 double totalPrices = 0d;
7 //策略模式
8 CashContext cc = new CashContext();
9 switch (cbxType.SelectedItem.ToString())
10 {
11 case "正常消费":
12 cc.setBehavior(new CashNormal());
13 break;
14 case "满300返100":
15 cc.setBehavior(new CashReturn("300", "100"));
16 break;
17 case "打8折":
18 cc.setBehavior(new CashRebate("0.8"));
19 break;
20 case "打7折":
21 cc.setBehavior(new CashRebate("0.7"));
22 break;
23 case "打5折":
24 cc.setBehavior(new CashRebate("0.5"));
25 break;
26 }
27 totalPrices = cc.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
28 //将每个商品合计计入总计
29 total = total + totalPrices;
30 //在列表框中显示信息
31 lbxList.Items.Add("单价:" + txtPrice.Text + " 数量:" + txtNum.Text + " 合计:" + totalPrices.ToString());
32 //在lblTotalShow标签上显示总计数
33 lblTotalShow.Text = total.ToString();
34 }
端知道所有的算法或行为的情况最初的策略模式是有缺点的,客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。 1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Threading.Tasks;
9 using System.Windows.Forms;
10 //add
11 using CCWin;
12 using System.Data.SqlClient;
13
14 namespace ExtendDiscountOfStrategyPatternWithReflection
15 {
16 using System.Reflection;
17
18 public partial class frmMain :Skin_Metro
19 {
20
21 DataSet ds; //用于存放配置文件信息
22
23 public frmMain()
24 {
25 InitializeComponent();
26 }
27
28 //声明一个double变量total来计算总计
29 double total = 0.0d;
30 private void btnConfirm_Click(object sender, EventArgs e)
31 {
32 //声明一个double变量totalPrices
33 double totalPrices = 0d;
34 //策略模式
35 CashContext cc = new CashContext();
36 //根据用户的选项,查询用户选择项的相关行
37 DataRow dr = ((DataRow[])ds.Tables[0].Select("name=‘" + cbxType.SelectedItem.ToString() + "‘"))[0];
38 //声明一个参数的对象数组
39 object[] args = null;
40 //若有参数,则将其分割成字符串数组,用于实例化时所用的参数
41 if (dr["para"].ToString() != "")
42 {
43 args = dr["para"].ToString().Split(‘,‘);
44 }
45 //通过反射实例化出相应的算法对象
46 cc.setBehavior((CashSuper)Assembly.Load("ExtendDiscountOfStrategyPatternWithReflection").
47 CreateInstance("ExtendDiscountOfStrategyPatternWithReflection." + dr["class"].ToString(), false,
48 BindingFlags.Default, null, args, null, null));
49
50 totalPrices = cc.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
51 //将每个商品合计计入总计
52 total = total + totalPrices;
53 //在列表框中显示信息
54 lbxList.Items.Add("单价:" + txtPrice.Text + " 数量:" + txtNum.Text + " 合计:" + totalPrices.ToString());
55 //在lblTotalShow标签上显示总计数
56 lblTotalShow.Text = total.ToString();
57 }
58
59 private void btnReset_Click(object sender, EventArgs e)
60 {
61 total = 0.0;
62 txtPrice.Text = "";
63 txtNum.Text = "";
64 lblTotalShow.Text = "";
65 lbxList.Items.Clear();
66 cbxType.SelectedIndex = 0;
67 }
68
69 private void txtNum_KeyPress(object sender, KeyPressEventArgs e)
70 {
71 //数字0~9所对应的keychar为48~57
72 e.Handled = true;
73 //输入0-9
74 if ((e.KeyChar >= 47 && e.KeyChar 58) || e.KeyChar == 8)
75 {
76 e.Handled = false;
77 }
78 }
79
80 private void txtPrice_KeyPress(object sender, KeyPressEventArgs e)
81 {
82 //数字0~9所对应的keychar为48~57
83 e.Handled = true;
84 //输入0-9
85 if ((e.KeyChar >= 47 && e.KeyChar 58) || (e.KeyChar == 8 || e.KeyChar==46))
86 {
87 e.Handled = false;
88 }
89 }
90
91 private void frmMain_Load(object sender, EventArgs e)
92 {
93 //读取配置文件
94 ds = new DataSet();
95 ds.ReadXml(Application.StartupPath + "\\CashAcceptType.xml");
96 //将读取到的记录绑定到下拉列表框中
97 foreach(DataRowView dr in ds.Tables[0].DefaultView)
98 {
99 cbxType.Items.Add(dr["name"].ToString());
100 }
101
102 //要下拉选择框在加载的时候,就选择索引为0的元素"正常消费"
103 cbxType.SelectedIndex = 0;
104 }
105 }
106 }
1 xml version="1.0" encoding="utf-8" ?>
2 CashAcceptType>
3 type>
4 name>正常消费name>
5 class>CashNormalclass>
6 para>para>
7 type>
8 type>
9 name>满300返100name>
10 class>CashReturnclass>
11 para>300,100para>
12 type>
13 type>
14 name>满200返50name>
15 class>CashReturnclass>
16 para>200,50para>
17 type>
18 type>
19 name>打8折name>
20 class>CashRebateclass>
21 para>0.8para>
22 type>
23 type>
24 name>打7折name>
25 class>CashRebateclass>
26 para>0.7para>
27 type>
28 type>
29 name>打5折name>
30 class>CashRebateclass>
31 para>0.5para>
32 type>
33 CashAcceptType>
文章标题:读《大话设计模式》——应用策略模式的"商场收银系统"(WinForm)
文章链接:http://soscw.com/index.php/essay/39025.html