最近写了一个应用策略模式的小程序。实现《大话策略模式》里面的商场收银系统。对里面的接口模式进行了一些改装,使得其更具封闭性。
使用WebForm实现了客户端。先来看看网页部分的主要代码。
<form id="form1" runat="server"> <div> <asp:TextBox ID="goodsName" runat="server"></asp:TextBox> <asp:TextBox ID="goodsPrice" runat="server"></asp:TextBox> <asp:TextBox ID="goodsNum" runat="server"></asp:TextBox> <asp:DropDownList ID="cbxType" runat="server"> <asp:ListItem Text="正常" Value="正常"></asp:ListItem> <asp:ListItem Text="打8折" Value="打8折"></asp:ListItem> <asp:ListItem Text="满300反100" Value="满300反100"></asp:ListItem> </asp:DropDownList> <asp:Button ID="btnOk" runat="server" Text="录入" OnClick="btnOk_click" /> <br /> <asp:TextBox ID="lbxList" runat="server" TextMode="MultiLine"></asp:TextBox> <%--<asp:Repeater ID="GoodsTable" runat="server"> <HeaderTemplate> <table class="goods"> <tr> <th>商品名称</th> <th>价格</th> <th>数量</th> <th>打折方式</th> <th>总价</th> </tr> </table> </HeaderTemplate> <ItemTemplate> </ItemTemplate> </asp:Repeater>--%> <br /> <asp:Label ID="lblResult" runat="server" Text="Label" EnableViewState="true"></asp:Label> <br /> <asp:Button ID="Button1" runat="server" Text="确认支付?" /> </div> </form>
注释部分暂时还没有实现,先用一个textbox代替了。一个简单的收银页面。后台的事件驱动代码:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.UI; 6 using System.Web.UI.WebControls; 7 using CollectionCode; 8 using System.Data; 9 public partial class _Default : System.Web.UI.Page 10 { 11 double total; 12 protected void Page_Load(object sender, EventArgs e) 13 { 14 if (!IsPostBack) { 15 total = 0.0d; 16 17 } 18 else { 19 //total = Convert.ToDouble(lblResult.Text); 20 } 21 22 } 23 public void btnOk_click(object sender, EventArgs e) { 24 ICollectionIO CaculateCash=new CashCollectionFactory(); 25 double totalPrice = 0d; 26 CaculateCash.InsertMoney=Convert.ToDouble(goodsPrice.Text) * Convert.ToDouble(goodsNum.Text); 27 CaculateCash.InsertCmd = cbxType.SelectedValue; 28 totalPrice = CaculateCash.ResultMoney; 29 total = total + totalPrice; 30 lbxList.Text+=goodsPrice.Text + " " + goodsNum.Text + " " + cbxType.SelectedValue.ToString() + " "+totalPrice.ToString()+"\n"; 31 lblResult.Text = total.ToString(); 32 } 33 }
可以看到botton_click部分的代码非常简洁。这是因为我把整个带接口的CollectionCode封装为一个.cs文件放在APP_Code里面了。我改变了书上示范的接口,只传递3个参数:InsertCmd,InsertMoney,返回ResultMoney。而封装了原示例中公开的函数。对于其他.cs外部的程序来说,除了这3个接口数据,其他的内部代码和实现方式是他们不必要也不能知道的。
CollectionCode如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 /// 将提供UML类图说明结构 6 namespace CollectionCode { 7 public interface ICollectionIO { 8 double InsertMoney { get; set; } 9 string InsertCmd { get; set; } 10 double ResultMoney { get; set; } 11 } 12 class CashSuper { 13 public virtual double AcceptCash(double money) { return money; } 14 } 15 class CashNormal : CashSuper { 16 public override double AcceptCash(double money) { 17 return money; 18 } 19 } 20 class CashRebate : CashSuper { 21 private double RebateValue = 1d; 22 public CashRebate(string RebateValueInsert) { 23 this.RebateValue = double.Parse(RebateValueInsert); 24 } 25 public override double AcceptCash(double money) { 26 return money * RebateValue; 27 } 28 } 29 class CashReturn : CashSuper { 30 private double _moneyCondition = 0.0d;//每moneyCondition钱返回ReturnValue钱 31 private double _ReturnValue = 0.0d; 32 public CashReturn(string moneyConditionInsert, string ReturnValueInsert) { 33 this._moneyCondition = double.Parse(moneyConditionInsert); 34 this._ReturnValue = double.Parse(ReturnValueInsert); 35 } 36 public override double AcceptCash(double money) { 37 double _result = money; 38 if (_result >= _moneyCondition) { 39 _result = _result - Math.Floor(money / _moneyCondition) * _ReturnValue; 40 } 41 return _result; 42 } 43 } 44 public class CashCollectionFactory:ICollectionIO { 45 public double InsertMoney { get; set; } 46 public string InsertCmd { get; set; } 47 public double ResultMoney { get { return GetResult(InsertMoney, InsertCmd); } set { this.ResultMoney = value; } } 48 static CashSuper createCashAccept(string paytype) { 49 CashSuper csbuild = null; 50 switch (paytype) { 51 case "正常": { 52 CashNormal csNormal = new CashNormal(); csbuild = csNormal; break; 53 } 54 case "满300反100": { 55 CashReturn csReturn = new CashReturn("300", "100"); csbuild = csReturn; break; 56 } 57 case "打8折": { 58 CashRebate csRebate = new CashRebate("0.8"); csbuild = csRebate; 59 //csbuild = new CashRebate("0.8"); 60 break; 61 } 62 default: break; 63 } 64 return csbuild; 65 } 66 double GetResult(double insertMoney, string insertCmd) { 67 return createCashAccept(insertCmd).AcceptCash(insertMoney); 68 } 69 } 70 71 }
基本借用了书中示例的策略模式。封装了所有方法。很多时候对于外部程序的请求其实就是一条string命令和几个参数。对于这种请求的处理应该全部在内部进行,而将内部的方法都封装起来。