今天我们通过一个“超市收银”业务来作为我们的示例(虽然这个示例看上去不太正常,但是它确表述我们所需要的)。我们将从业务分析到业务建模然后最后的编码来用“面向领域对象”的方式来做我们的项目。
好,我们开始吧!
一、业务分析
大家都去超市买过东西,对超市收银业务都比较熟悉。什么?你不熟?好吧,那我们找个收银员给大家讲解下(领域专家)。
收银员小慧:哦,是这样呢。顾客排队银帐我就收银呢,我要使用收银机呢。收银机就能计算出要收的钱呢,我就扫一下呢,就OK了呢。然后就收银了呢。
听了小慧的讲解,我们心中有了业务的概念了。我们这里采用《业务关键字分析法》来找出此业务流程里面的一些关系字:
商品
顾客
收银员
收银机
*收银
*选商品
*收银员使用收银机
*收银机扫商品计算金额
好了,列出这些“业务关键字”了,我们就可以建我们的对象模型了。
二、系统建模
上面我们分析出了一些“业务关键字”接下来我们分析这些业务关键字并深入他们的业务。
商品对象(Goods)。
属性:商品名称(GoodsName)、商品价格(GoodsPrice)。
行为:在这里商品对象是没有行为的,我们也可以叫它“值对象”。
顾客对象(Customer)。
属性:顾客姓名(CustomerName)、顾客选购的商品(Goodss)
行为:选购想买的商品(LikeBuy)、听收银员说要收多少RMB(ListenAmount)
收银员对象(Cashier)。
属性:收银员姓名(CashierName)
行为:收银(CashierRegister)
收银机对象(CashierRegister)。
属性:收银机编号(CashRegisterNo)
字段:总金额(_totalAmount)
行为:收银(CashRegisters)、显示收银总额(ShowAmount)
有木有!有木有?有木有很直观,这也就是面向对象分析的好处,因为对象就是对现实的抽象,我们现实中的事务可以很方便的用对象抽象出来。我们很容易发现,这和用表来描述这些业务模型显然要不方便的多。表还只能描述属性,造成了属性与行为的分离。
三、代码示例
商品对象
/// <summary> /// 商品 /// </summary> public class Goods { /// <summary> /// 对象标识 /// </summary> public Guid OKey { get ; set ; } /// <summary> /// 商品名称 /// </summary> public string GoodsName { get ; set ; } /// <summary> /// 商品价格 /// </summary> public decimal GoodsPrice { get ; set ; } }
顾客对象
/// <summary> /// 顾客 /// </summary> public class Customer { /// <summary> /// 对象标识 /// </summary> public Guid OKey { get ; set ; } /// <summary> /// 顾客姓名 /// </summary> public string CustomerName { get ; set ; } private List < Goods > _goodss = new List < Goods > (); /// <summary> /// 顾客购买的商品 /// </summary> public List < Goods > Goodss { get { return _goodss; } set { _goodss = value; } } /// <summary> /// 顾客选购商品 /// </summary> /// <param name="goods"> 商品 </param> public void LikeBuy(Goods goods) { this ._goodss.Add(goods); } /// <summary> /// 听收银员应收多少钱 /// </summary> /// <param name="amount"></param> public void ListenAmount( decimal amount) { Console.WriteLine( " 我是[{0}],我买了{1}件商品。我共花了{2}元RMB。 " , this .CustomerName, this .Goodss.Count, amount.ToString( " f2 " )); }
收银员对象
/// <summary> /// 收银员 /// </summary> public class Cashier { /// <summary> /// 对象标识 /// </summary> public Guid OKey { get ; set ; } /// <summary> /// 收银员姓名 /// </summary> public string CashierName { get ; set ; } /// <summary> /// 收银 /// </summary> /// <param name="customer"> 顾客 </param> public void CashRegister(Customer customer) { // 打开使用收银机 CashRegister cashRegister = new CashRegister(); // 对顾客的商品进行收银机扫码,收银 foreach (var goods in customer.Goodss) { // 使用收银机扫商品进行收银 cashRegister.CashRegisters(goods); } // 通知顾客一共收多少钱 customer.ListenAmount(cashRegister.ShowAmount()); } }
收银机对象
/// <summary> /// 对象标识 /// </summary> public Guid OKey { get ; set ; } /// <summary> /// 收银机编号 /// </summary> public string CashRegisterNo { get ; set ; } /// <summary> /// 总价格 /// </summary> private decimal _totalAmount { get ; set ; } public CashRegister() { // 收银总额置0 this ._totalAmount = 0 ; } /// <summary> /// 收银 /// </summary> /// <param name="goods"> 商品 </param> public void CashRegisters(Goods goods) { this ._totalAmount += goods.GoodsPrice; } /// <summary> /// 显示收银总额 /// </summary> /// <returns></returns> public decimal ShowAmount() { return this ._totalAmount; }
模拟业务流程
// 我们创建几样商品 Goods RedWine = new Goods() { GoodsName = " 红酒 " , GoodsPrice = 1800 ,OKey = Guid.NewGuid() }; Goods Condoms = new Goods() { GoodsName = " 安全套 " , GoodsPrice = 35 ,OKey = Guid.NewGuid() }; // 我们创建几位顾客 Customer Chunge = new Customer() { CustomerName = " 春哥 " , OKey = Guid.NewGuid() }; Customer Beianqi = new Customer() { CustomerName = " 贝安琪 " , OKey = Guid.NewGuid() }; // 当然,我们需要收银员啊 Cashier CashierMM = new Cashier() { CashierName = " 收银员MM " , OKey = Guid.NewGuid() }; // 顾客逛了一圈,选了自己想要的商品 Chunge.LikeBuy(RedWine); Beianqi.LikeBuy(RedWine); Beianqi.LikeBuy(Condoms); // 顾客开始排队结帐了 Queue < Customer > customerQueue = new Queue < Customer > (); customerQueue.Enqueue(Chunge); customerQueue.Enqueue(Beianqi); // 队伍过来,按先后顺序挨个收银喽 foreach (var customer in customerQueue) { // 收银 CashierMM.CashRegister(customer); }
显示结果
上面的例子虽然不是很恰当,但是它也很好的像我们表达出了领域驱动分析问题、面向对象驱动开发的好处了。
最后大家回想一下,用数据库表驱动的方式。分析这个业务会是什么样子的。。。。