[原创][推荐]C#设计模式-命令模式(POS收银台应用)

[原创]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>
/// 输入货品, 检测输入的命令是货品编号 //如转载请注明出处,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("输入非法命令!");
   }
}



收银台业务逻辑类,业务处理中心。请参考源代码。

贴图图片

/// <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);
   }
}


显示屏用户控件(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;
   }
}



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
posted @ 2009-12-27 22:01  C#爱好者  阅读(1646)  评论(2编辑  收藏  举报