超市收银业务来说明领域对象驱动开发

今天我们通过一个“超市收银”业务来作为我们的示例(虽然这个示例看上去不太正常,但是它确表述我们所需要的)。我们将从业务分析到业务建模然后最后的编码来用“面向领域对象”的方式来做我们的项目。

一、业务分析

大家应该对超市收银业务都比较熟悉。我们来找个收银员给大家讲解下(领域专家)。

收银员小慧:哦,是这样呢。顾客拿到自己想要买的东西,在收银台排队结帐,我打开收银机。扫一下顾客买的商品,收银机就能计算出要收的钱。然后就收银了。

听了小慧的讲解,我们心中有了业务的概念了。我们这里采用《业务关键字分析法》来找出此业务流程里面的一些关系字:

  • 商品
  • 顾客
  • 选商品
  • 收银员
  • 收银机
  • 收银员使用收银机
  • 收银机扫商品计算金额
  • 收银

好了,列出这些“业务关键字”了,我们就可以建我们的对象模型了。

二、系统建模

上面我们分析出了一些“业务关键字”接下来我们分析这些业务关键字并深入他们的业务。

商品对象(Goods)。
属性:商品名称(GoodsName)、商品价格(GoodsPrice)。
行为:在这里商品对象是没有行为的,我们也可以叫它“值对象”。

顾客对象(Customer)。
属性:顾客姓名(CustomerName)、顾客选购的商品(Goodss)
行为:选购想买的商品(LikeBuy)、听收银员说要收多少RMB(ListenAmount)

收银员对象(Cashier)。
属性:收银员姓名(CashierName)
行为:收银(CashierRegister)

收银机对象(CashierRegister)。
属性:收银机编号(CashRegisterNo)
字段:总金额(_totalAmount)
行为:收银(CashRegisters)、显示收银总额(ShowAmount)

image.png

有木有很直观,这也就是面向对象分析的好处,因为对象就是对现实的抽象,我们现实中的事务可以很方便的用对象抽象出来。我们很容易发现,这和用表来描述这些业务模型显然要不方便的多。表还只能描述属性,造成了属性与行为的分离。

三、代码示例

商品对象

/// 
/// 商品
/// 
public class Goods
{
    /// 
    /// 对象标识
    /// 
    public Guid OKey { get; set; }
    /// 
    /// 商品名称
    /// 
    public string GoodsName { get; set; }
    /// 
    /// 商品价格
    /// 
    public decimal GoodsPrice { get; set; }
}

顾客对象

/// 
/// 顾客
/// 
public class Customer
{
    /// 
    /// 对象标识
    /// 
    public Guid OKey { get; set; }
    /// 
    /// 顾客姓名
    /// 
    public string CustomerName { get; set; }

    private List _goodss = new List();
    /// 
    /// 顾客购买的商品
    /// 
    public List Goodss
    {
        get { return _goodss; }
        set { _goodss = value; }
    }

    /// 
    /// 顾客选购商品
    /// 
    /// 商品
    public void LikeBuy(Goods goods)
    {
        this._goodss.Add(goods);
    }

    /// 
    /// 听收银员应收多少钱
    /// 
    /// 
    public void ListenAmount(decimal amount)
    {
        Console.WriteLine("我是[{0}],我买了{1}件商品。我共花了{2}元RMB。", this.CustomerName, this.Goodss.Count, amount.ToString("f2"));
    }

收银员对象

/// 
/// 收银员
/// 
public class Cashier
{
    /// 
    /// 对象标识
    /// 
    public Guid OKey { get; set; }
    /// 
    /// 收银员姓名
    /// 
    public string CashierName { get; set; }

    /// 
    /// 收银
    /// 
    /// 顾客
    public void CashRegister(Customer customer)
    {
        //打开使用收银机
        CashRegister cashRegister = new CashRegister();

        //对顾客的商品进行收银机扫码,收银
        foreach (var goods in customer.Goodss)
        {
            //使用收银机扫商品进行收银
            cashRegister.CashRegisters(goods);
        }

        //通知顾客一共收多少钱
        customer.ListenAmount(cashRegister.ShowAmount());
    }
}

收银机对象

/// 
/// 收银机
/// 
public class CashierRegister
{
    /// 
    /// 对象标识
    /// 
    public Guid OKey { get; set; }
    /// 
    /// 收银机编号
    /// 
    public string CashRegisterNo { get; set; }

    /// 
    /// 总价格
    /// 
    private decimal _totalAmount { get; set; }

    public CashRegister()
    {
        //收银总额置0
        this._totalAmount = 0;
    }

    /// 
    /// 收银
    /// 
    /// 商品
    public void CashRegisters(Goods goods)
    {
        this._totalAmount += goods.GoodsPrice;
    }

    /// 
    /// 显示收银总额
    /// 
    /// 
    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 customerQueue = new Queue();
customerQueue.Enqueue(Chunge);
customerQueue.Enqueue(Beianqi);

//队伍过来,按先后顺序挨个收银喽
foreach (var customer in customerQueue)
{
    //收银
    CashierMM.CashRegister(customer);
}

显示结果


image.png

上面的例子虽然不是很恰当,但是它也很好的像我们表达出了领域驱动分析问题、面向对象驱动开发的好处了。最后大家回想一下,用数据库表驱动的方式。分析这个业务会是什么样子的!

你可能感兴趣的:(超市收银业务来说明领域对象驱动开发)