《戏说对象程序设计C#版》从一个简单的商场收银程序开始谈起,一步一步提出问题并改善设计,在此过程中,画龙点睛地谈到几种设计模式:复制/黏贴→业务封装→简单工厂模式→策略模式→改良策略模式(用反射)→三层架构,分层开发(Dal+Bll+Ui)+门面模式(facade)。
不过,没有严格按照书上说的把三层严格分开放到不同的项目中。
一、 数据访问层(DAl): XML文件:cash.xml
正常收费
cashNormal
满300 返100
cashReturn
300,100
满200 返50
cashReturn
200,50
打8 折
cashRebate
0.8
打7 折
cashRebate
0.7
Dal 读取数据:
using System.Data;
namespace wfa2.dal
{
class cashType
{
public DataSet getCashType()
{
DataSet ds = new DataSet();
ds.ReadXml(@"c:\cash.xml");
return ds;
}
}
}
二、模型(Model 收银算法)
namespace wfa2.model
{
abstract class cashSuper
{
public abstract double acceptCash(double money);
}
class cashNormal : cashSuper
{
public override double acceptCash(double money)
{
return money;
}
}
class cashRebate : cashSuper
{
private double rebate=1d;
public cashRebate(double rebate)
{
this.rebate = rebate;
}
public override double acceptCash(double money)
{
return money*this.rebate;
}
}
class cashReturn : cashSuper
{
private double condition=0.0d;
private double mnyReturn=0.0d;
public cashReturn(double condition,double mnyReturn)
{
this.condition = condition;
this.mnyReturn=mnyReturn;
}
public override double acceptCash(double money)
{
return (money>=this.condition)?money-mnyReturn:money;
}
}
class cashContext
{
private cashSuper cs;
public cashContext(cashSuper cs)
{
this.cs = cs;
}
public double getResult(double money)
{
return cs.acceptCash(money);
}
}
}
三、业务逻辑层(Bll,“门面”,负责底层数据与UI之间的信息的沟通传递)using System;
using System.Data;
using System.Reflection;
using wfa2.model;
namespace wfa2.Bll
{
class cashFacde
{
private DataSet ds ;
const string ASSEMBLY_NAME = "wfa2";
public DataSet getCashTypes()
{
wfa2.dal.cashType type = new wfa2.dal.cashType();
this.ds = type.getCashType();
/* int rowCnt = ds.Tables[0].DefaultView.Count;
object[] types = new object[rowCnt];
for (int i = 0; i < rowCnt; i++)
{
types[i] = ds.Tables[0].DefaultView[i]["name"].ToString();
}
return types;*/
return this.ds;
}
public double getCash(string type, double moeny)
{
object[] args = null;
DataRow row = this.ds.Tables[0].Select("name='" + type + "'")[0];
args = row["para"].ToString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
//为了方便,书中几个收银算法的构造函数都是字符串型的,我做了改动,参数全是Double,所以要稍 微进行转换
object[] paras = new object[args.Length];
for (int i = 0; i < args.Length ; i++)
{
paras[i] = double.Parse(args[i].ToString());
}
cashSuper cs = (cashSuper)Assembly.Load(ASSEMBLY_NAME).CreateInstance(ASSEMBLY_NAME + ".model." + row["class"].ToString(), true, BindingFlags.Default, null, paras, null, null);
cashContext cc = new cashContext(cs);
return cc.getResult(moeny);
}
}
}
四、展示层(UI)前端页面:
namespace wfa2
{
partial class frmMarket
{
///
/// Required designer variable.
/// private System.ComponentModel.IContainer components = null;
///
/// Clean up any resources being used.
/// ///
true if managed resources should be disposed; otherwise, false.
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.label5 = new System.Windows.Forms.Label();
this.boxPromt = new System.Windows.Forms.ComboBox();
this.txtTotal = new System.Windows.Forms.MaskedTextBox();
this.label4 = new System.Windows.Forms.Label();
this.button2 = new System.Windows.Forms.Button();
this.button1 = new System.Windows.Forms.Button();
this.txtQty = new System.Windows.Forms.MaskedTextBox();
this.txtPrice = new System.Windows.Forms.MaskedTextBox();
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.BackColor = System.Drawing.Color.WhiteSmoke;
this.panel1.Controls.Add(this.label5);
this.panel1.Controls.Add(this.boxPromt);
this.panel1.Controls.Add(this.txtTotal);
this.panel1.Controls.Add(this.label4);
this.panel1.Controls.Add(this.button2);
this.panel1.Controls.Add(this.button1);
this.panel1.Controls.Add(this.txtQty);
this.panel1.Controls.Add(this.txtPrice);
this.panel1.Controls.Add(this.label3);
this.panel1.Controls.Add(this.label2);
this.panel1.Location = new System.Drawing.Point(12, 35);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(423, 296);
this.panel1.TabIndex = 0;
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(65, 110);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(65, 12);
this.label5.TabIndex = 10;
this.label5.Text = "促销信息:";
//
// boxPromt
//
this.boxPromt.FormattingEnabled = true;
this.boxPromt.Location = new System.Drawing.Point(136, 107);
this.boxPromt.Name = "boxPromt";
this.boxPromt.Size = new System.Drawing.Size(196, 20);
this.boxPromt.TabIndex = 9;
//
// txtTotal
//
this.txtTotal.Location = new System.Drawing.Point(136, 167);
this.txtTotal.Name = "txtTotal";
this.txtTotal.ReadOnly = true;
this.txtTotal.Size = new System.Drawing.Size(196, 21);
this.txtTotal.TabIndex = 8;
this.txtTotal.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(75, 176);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(41, 12);
this.label4.TabIndex = 7;
this.label4.Text = "总计:";
//
// button2
//
this.button2.Location = new System.Drawing.Point(94, 213);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 5;
this.button2.Text = "重置";
this.button2.UseVisualStyleBackColor = true;
//
// button1
//
this.button1.Location = new System.Drawing.Point(239, 213);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 4;
this.button1.Text = "确定";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// txtQty
//
this.txtQty.Location = new System.Drawing.Point(136, 70);
this.txtQty.Mask = "999999";
this.txtQty.Name = "txtQty";
this.txtQty.Size = new System.Drawing.Size(196, 21);
this.txtQty.TabIndex = 3;
this.txtQty.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
//
// txtPrice
//
this.txtPrice.Location = new System.Drawing.Point(136, 29);
this.txtPrice.Mask = "9999999.99";
this.txtPrice.Name = "txtPrice";
this.txtPrice.Size = new System.Drawing.Size(196, 21);
this.txtPrice.TabIndex = 2;
this.txtPrice.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(75, 73);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(41, 12);
this.label3.TabIndex = 1;
this.label3.Text = "数量:";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(75, 32);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(41, 12);
this.label2.TabIndex = 0;
this.label2.Text = "单价:";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(26, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(53, 12);
this.label1.TabIndex = 1;
this.label1.Text = "商场管理";
//
// frmMarket
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.LightSteelBlue;
this.ClientSize = new System.Drawing.Size(440, 358);
this.Controls.Add(this.label1);
this.Controls.Add(this.panel1);
this.Name = "frmMarket";
this.Text = "frmMarket";
this.Load += new System.EventHandler(this.frmMarket_Load);
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.MaskedTextBox txtQty;
private System.Windows.Forms.MaskedTextBox txtPrice;
private System.Windows.Forms.MaskedTextBox txtTotal;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.ComboBox boxPromt;
private System.Windows.Forms.Label label5;
}
}
把不同的部分放在不同的文件中,应该都可以运行,特别注意的是我的文件的namespace是wfa2,把wfa2改成自己的命名空间,应该都可以用。