[原创]C#设计模式-命令模式(POS收银台应用)
命令模式(Command Pattern)
源代码下载:
http://www.vjsdn.com/bbs/bbsTopicDetails.aspx?pid=112271249
POS收银台处理用户输入最适合演示命令模式,收银员通过扫描枪读取货品条码,使用快键或输入命令进行结帐或打印小票,或处理其它功能,我将每一个操作定义为命令,用编程语言实现只要执行命令(Execute Command)即可。
先看收银界面:
收银界面初始状态,程序运行或结帐完毕显示的界面。
输入"VC"命令,显示维它命C产品名称和单价。
用户输入命令处理流程:
当用户按回车键,分析命令。
private void OnCommand_KeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyCode == Keys.Enter) && (txtCommand.Text.Trim() != ""))
{
//CommandBase command = CommandFactory.CreateCommand(_pos, txtCommand.Text);
CommandBase command = _pos.ParseCommand(txtCommand.Text);
command.Execute();
txtCommand.Clear();//清空输入框
}
}
收银命令定义:
CommandBase是所有命令的基类,定义一个Execute方法(执行该命令)。
/// <summary>
/// 定义命令基类
/// </summary>
public class CommandBase
{
protected POS _POS;
/// <summary>
/// 执行命令
/// </summary>
public virtual void Execute() { }
}
/// 定义命令基类
/// </summary>
public class CommandBase
{
protected POS _POS;
/// <summary>
/// 执行命令
/// </summary>
public virtual void Execute() { }
}
其它命令定义:
/// <summary>
/// 输入货品, 检测输入的命令是货品编号 //如转载请注明出处,by 易学网 www.vjsdn.com
/// </summary>
public class CommandInputStock : CommandBase
{
private Stock _stock;
public CommandInputStock(POS pos, Stock stock)
{
_POS = pos;
_stock = stock;
}
public override void Execute()
{
_POS.InputStock(_stock);
}
}
/// <summary>
/// 收银命令,进入收银状态
/// </summary>
public class CommandSetReceiveMode : CommandBase
{
public CommandSetReceiveMode(POS pos)
{
_POS = pos;
}
public override void Execute()
{
_POS.SetReceiveMode();
}
}
/// <summary>
/// 输入收银金额
/// </summary>
public class CommandReceiveMoney : CommandBase
{
private decimal _money = 0;
public CommandReceiveMoney(POS pos, decimal money)
{
_POS = pos;
_money = money;
}
public override void Execute()
{
_POS.ReceiveMoney(_money);
}
}
/// <summary>
/// 打印小票命令
/// </summary>
public class CommandPrintBill : CommandBase
{
public CommandPrintBill(POS pos)
{
_POS = pos;
}
public override void Execute()
{
_POS.PrintBill();
}
}
/// <summary>
/// 收银/结帐命令
/// </summary>
public class CommandCheckOut : CommandBase
{
public CommandCheckOut(POS pos)
{
_POS = pos;
}
public override void Execute()
{
_POS.CheckOut();
}
}
/// <summary>
/// 取消当前交易
/// </summary>
public class CommandCancelTransaction : CommandBase
{
public CommandCancelTransaction(POS pos)
{
_POS = pos;
}
public override void Execute()
{
if (DialogResult.Yes == MessageBox.Show("要取消交易吗?", "确认程序", MessageBoxButtons.YesNo))
{
_POS.Reset();
}
}
}
/// <summary>
/// 退出系统命令
/// </summary>
public class CommandExit : CommandBase
{
public CommandExit(POS pos)
{
_POS = pos;
}
public override void Execute()
{
if (DialogResult.Yes == MessageBox.Show("要退出系统吗?", "确认程序", MessageBoxButtons.YesNo))
{
Application.Exit();
}
}
}
/// 输入货品, 检测输入的命令是货品编号 //如转载请注明出处,by 易学网 www.vjsdn.com
/// </summary>
public class CommandInputStock : CommandBase
{
private Stock _stock;
public CommandInputStock(POS pos, Stock stock)
{
_POS = pos;
_stock = stock;
}
public override void Execute()
{
_POS.InputStock(_stock);
}
}
/// <summary>
/// 收银命令,进入收银状态
/// </summary>
public class CommandSetReceiveMode : CommandBase
{
public CommandSetReceiveMode(POS pos)
{
_POS = pos;
}
public override void Execute()
{
_POS.SetReceiveMode();
}
}
/// <summary>
/// 输入收银金额
/// </summary>
public class CommandReceiveMoney : CommandBase
{
private decimal _money = 0;
public CommandReceiveMoney(POS pos, decimal money)
{
_POS = pos;
_money = money;
}
public override void Execute()
{
_POS.ReceiveMoney(_money);
}
}
/// <summary>
/// 打印小票命令
/// </summary>
public class CommandPrintBill : CommandBase
{
public CommandPrintBill(POS pos)
{
_POS = pos;
}
public override void Execute()
{
_POS.PrintBill();
}
}
/// <summary>
/// 收银/结帐命令
/// </summary>
public class CommandCheckOut : CommandBase
{
public CommandCheckOut(POS pos)
{
_POS = pos;
}
public override void Execute()
{
_POS.CheckOut();
}
}
/// <summary>
/// 取消当前交易
/// </summary>
public class CommandCancelTransaction : CommandBase
{
public CommandCancelTransaction(POS pos)
{
_POS = pos;
}
public override void Execute()
{
if (DialogResult.Yes == MessageBox.Show("要取消交易吗?", "确认程序", MessageBoxButtons.YesNo))
{
_POS.Reset();
}
}
}
/// <summary>
/// 退出系统命令
/// </summary>
public class CommandExit : CommandBase
{
public CommandExit(POS pos)
{
_POS = pos;
}
public override void Execute()
{
if (DialogResult.Yes == MessageBox.Show("要退出系统吗?", "确认程序", MessageBoxButtons.YesNo))
{
Application.Exit();
}
}
}
命令工厂(Command Factory)
判断用户输入的字符串并创建命令对象,如用户输入无法辨识的字符串则创建CommandNull对象。
这里引用Null Object 模式,关于Null Object模式请参考其它文献。
CommandNull类
/// <summary>
/// NULL Object 模式
/// </summary>
public class CommandNull : CommandBase
{
public override void Execute()
{
MessageBox.Show("输入非法命令!");
}
}
/// NULL Object 模式
/// </summary>
public class CommandNull : CommandBase
{
public override void Execute()
{
MessageBox.Show("输入非法命令!");
}
}
收银台业务逻辑类,业务处理中心。请参考源代码。
/// <summary>
/// 由收银台输入货品编号,返回Stock实体对象。
/// 这里可以从SQL Server取数。
/// </summary>
public class POS
{
//如转载请注明出处,by 易学网 www.vjsdn.com
private ucMonitor _Monitor; //收银显示屏
private IList _StockList = new ArrayList(); //货品列表
private decimal _ReceivedMoney = 0; //客户支付(现金或借记卡)的金额
private decimal _ReceivableTotal = 0;//客户应付金额
private bool _ReceiveMode = false;
public bool IsReceiveMode { get { return _ReceiveMode; } }
public POS(ucMonitor monitor)
{
_Monitor = monitor;
this.Reset();
}
/// <summary>
/// 重设收银台
/// </summary>
public void Reset()
{
_ReceiveMode = false;
_ReceivedMoney = 0;
_ReceivableTotal = 0;
_StockList.Clear();
_Monitor.ShowWelcome();
_Monitor.ShowStatus(PosMode.InputStock);
}
/// <summary>
/// 检测输入命令
/// </summary>
public CommandBase ParseCommand(string commandString)
{
//首长检查输入的命令是否货品编号
Stock stock = this.GetStock(commandString);
if (stock != null)
return new CommandInputStock(this, stock);
else
return CommandFactory.CreateCommand(this, commandString);
}
//测试用.可创建两个货品对象
private Stock GetStock(string code)
{
code = code.ToUpper();
if (code == "VC".ToUpper())
return new Stock("Vit.C", decimal.Parse("5.8"));
else if (code == "PP".ToUpper())
return new Stock("Panicilin", decimal.Parse("15.20"));
else
return null;
}
// 这里可以从SQL Server取数。
private static Stock GetStockFromSQL(string code)
{
//连接SQL Server.查询记录,返回Datarow,将Datarow 转换为Stock
return null;
}
/// <summary>
/// 输入货品
/// </summary>
/// <param name="stock"></param>
public void InputStock(Stock stock)
{
_StockList.Add(stock);
//累加应收金额
_ReceivableTotal += stock.Price;
_Monitor.ShowCurrentStock(stock);
}
/// <summary>
/// 结帐
/// </summary>
public void CheckOut()
{
if (_ReceivedMoney > 0 || _ReceivableTotal > 0)
{
if (_ReceivedMoney >= _ReceivableTotal)
{
this.PrintBill();//打印小票
this.Reset(); //处理下一位客户
MessageBox.Show("打印完毕,处理下一位客户。");
}
else
{
MessageBox.Show("金额不足,不能结帐....");
}
}
else
{
MessageBox.Show("大哥,没有输入货品,不能结帐!");
}
}
/// <summary>
/// 打印小票
/// </summary>
public void PrintBill()
{
string msg = string.Format("总共{0}个货品\r\n\r\n正在打印小票...", _StockList.Count);
MessageBox.Show(msg);
}
/// <summary>
/// 设置收银模式
/// </summary>
public void SetReceiveMode()
{
_ReceiveMode = true;
_Monitor.ShowStatus(PosMode.CheckBill);
}
/// <summary>
/// 收款
/// </summary>
/// <param name="money"></param>
public void ReceiveMoney(decimal money)
{
_ReceivedMoney = money;
_Monitor.ShowReceive(money);
}
}
/// 由收银台输入货品编号,返回Stock实体对象。
/// 这里可以从SQL Server取数。
/// </summary>
public class POS
{
//如转载请注明出处,by 易学网 www.vjsdn.com
private ucMonitor _Monitor; //收银显示屏
private IList _StockList = new ArrayList(); //货品列表
private decimal _ReceivedMoney = 0; //客户支付(现金或借记卡)的金额
private decimal _ReceivableTotal = 0;//客户应付金额
private bool _ReceiveMode = false;
public bool IsReceiveMode { get { return _ReceiveMode; } }
public POS(ucMonitor monitor)
{
_Monitor = monitor;
this.Reset();
}
/// <summary>
/// 重设收银台
/// </summary>
public void Reset()
{
_ReceiveMode = false;
_ReceivedMoney = 0;
_ReceivableTotal = 0;
_StockList.Clear();
_Monitor.ShowWelcome();
_Monitor.ShowStatus(PosMode.InputStock);
}
/// <summary>
/// 检测输入命令
/// </summary>
public CommandBase ParseCommand(string commandString)
{
//首长检查输入的命令是否货品编号
Stock stock = this.GetStock(commandString);
if (stock != null)
return new CommandInputStock(this, stock);
else
return CommandFactory.CreateCommand(this, commandString);
}
//测试用.可创建两个货品对象
private Stock GetStock(string code)
{
code = code.ToUpper();
if (code == "VC".ToUpper())
return new Stock("Vit.C", decimal.Parse("5.8"));
else if (code == "PP".ToUpper())
return new Stock("Panicilin", decimal.Parse("15.20"));
else
return null;
}
// 这里可以从SQL Server取数。
private static Stock GetStockFromSQL(string code)
{
//连接SQL Server.查询记录,返回Datarow,将Datarow 转换为Stock
return null;
}
/// <summary>
/// 输入货品
/// </summary>
/// <param name="stock"></param>
public void InputStock(Stock stock)
{
_StockList.Add(stock);
//累加应收金额
_ReceivableTotal += stock.Price;
_Monitor.ShowCurrentStock(stock);
}
/// <summary>
/// 结帐
/// </summary>
public void CheckOut()
{
if (_ReceivedMoney > 0 || _ReceivableTotal > 0)
{
if (_ReceivedMoney >= _ReceivableTotal)
{
this.PrintBill();//打印小票
this.Reset(); //处理下一位客户
MessageBox.Show("打印完毕,处理下一位客户。");
}
else
{
MessageBox.Show("金额不足,不能结帐....");
}
}
else
{
MessageBox.Show("大哥,没有输入货品,不能结帐!");
}
}
/// <summary>
/// 打印小票
/// </summary>
public void PrintBill()
{
string msg = string.Format("总共{0}个货品\r\n\r\n正在打印小票...", _StockList.Count);
MessageBox.Show(msg);
}
/// <summary>
/// 设置收银模式
/// </summary>
public void SetReceiveMode()
{
_ReceiveMode = true;
_Monitor.ShowStatus(PosMode.CheckBill);
}
/// <summary>
/// 收款
/// </summary>
/// <param name="money"></param>
public void ReceiveMoney(decimal money)
{
_ReceivedMoney = money;
_Monitor.ShowReceive(money);
}
}
显示屏用户控件(Monitor) ,用于显示货品信息及收银状态。
public partial class ucMonitor : UserControl
{
private decimal _receivable = 0;
public ucMonitor()
{
InitializeComponent();
}
//如转载请注明出处,by 易学网 www.vjsdn.com
//显示当前货品
public void ShowCurrentStock(Stock stock)
{
string msg = "名称:{0} 单价:{1}";
lblCurStock.Text = string.Format(msg, stock.Name, stock.Price.ToString());
_receivable += stock.Price;
lblRecevable.Text = "应收:" + _receivable.ToString();
}
//显示收款
public void ShowReceive(decimal money)
{
lblCurStock.Text = "收到:" + money.ToString();
lblCharge.Text = "找回:" + (money - _receivable).ToString();
}
//刷新显示屏
public void Reset()
{
lblCurStock.Text = "";
lblRecevable.Text = "";
lblCharge.Text = "";
}
//显示欢迎消息
public void ShowWelcome()
{
this.Reset();
lblCurStock.Text = "欢迎光临易学网";
}
//显示收银状态
public void ShowStatus(PosMode mode)
{
string status = "准备就绪";
if (PosMode.CheckBill == mode) status = "结帐";
if (PosMode.InputStock == mode) status = "输入货品";
lblStatus.Text = "状态:" + status;
}
}
{
private decimal _receivable = 0;
public ucMonitor()
{
InitializeComponent();
}
//如转载请注明出处,by 易学网 www.vjsdn.com
//显示当前货品
public void ShowCurrentStock(Stock stock)
{
string msg = "名称:{0} 单价:{1}";
lblCurStock.Text = string.Format(msg, stock.Name, stock.Price.ToString());
_receivable += stock.Price;
lblRecevable.Text = "应收:" + _receivable.ToString();
}
//显示收款
public void ShowReceive(decimal money)
{
lblCurStock.Text = "收到:" + money.ToString();
lblCharge.Text = "找回:" + (money - _receivable).ToString();
}
//刷新显示屏
public void Reset()
{
lblCurStock.Text = "";
lblRecevable.Text = "";
lblCharge.Text = "";
}
//显示欢迎消息
public void ShowWelcome()
{
this.Reset();
lblCurStock.Text = "欢迎光临易学网";
}
//显示收银状态
public void ShowStatus(PosMode mode)
{
string status = "准备就绪";
if (PosMode.CheckBill == mode) status = "结帐";
if (PosMode.InputStock == mode) status = "输入货品";
lblStatus.Text = "状态:" + status;
}
}
Stock对象,货品对象。
/// <summary>
/// 货品类 如转载请注明出处,by 易学网 www.vjsdn.com
/// </summary>
public class Stock
{
private string _Name = string.Empty;
private decimal _Price = 0;
public Stock(string name, decimal price)
{
_Name = name;
_Price = price;
}
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public decimal Price
{
get { return _Price; }
set { _Price = value; }
}
}
/// 货品类 如转载请注明出处,by 易学网 www.vjsdn.com
/// </summary>
public class Stock
{
private string _Name = string.Empty;
private decimal _Price = 0;
public Stock(string name, decimal price)
{
_Name = name;
_Price = price;
}
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public decimal Price
{
get { return _Price; }
set { _Price = value; }
}
}
如转载请注明出处,by 易学网 www.vjsdn.com