面向对象设计领域的著作汗牛充栋,其中不乏大师精品。然而大部分研究对象(或者说描述对象)都是静态的模型,典型的如——设计模式、SOLID等等。
在开始介绍动态面向对象建模之前,我们先来给动态面向对象建模下个定义。
静态模型 | 动态模型 | 备注 |
---|---|---|
Class | Object | 一个Bird类是静态模型;一只麻雀是动态模型。后者考虑具体的这个实例的生命周期——创建、初始化、装配、解构、销毁等等。 |
Attribute | State | Bird类里面包含一个Eye属性;一只麻雀的左眼。麻雀眼睛是不是要闭上? |
Method | Interactions | Bird累里面包含一个Fly方法;一只企鹅的Fly方法是应该抛出异常,还是实现为跳跃? |
Class relationship | Object relationship | Bird类是Animal的子类;这只麻雀是另一只麻雀的妈妈。 |
Responsibility | Business Logic | Bird类负责鸟的鸣叫、飞行、睡眠等操作;一只麻雀睡觉的时候是不是要闭上眼睛。 |
每个人每天都在做动态建模,所有的设计最终都落实在动态建模上面,无论是有意识的还是无意识的。当你写下 new Order()
的的时候你就在决定如何初始化一个订单的实例。这里面有多少个决策点?
Order的属性是在构造函数传入还是用Setters传入?
Order是自己创建还是由框架装配?
Order是否是一个POJO?为什么?
Order是否可以保存自己?Active Record vs Data Mapper
Order是否是Immutable的?
根据以下规则计算商品总价:
江浙沪100元以上免运费;
大陆其他地区运费为价格的3%;
澳大利亚加收商品税10%,运费为价格的5%;
其他国际地区加收商品税17%,运费为价格的7%。
客户地址 | 商品税 | 订单价格 | 运费标准 |
---|---|---|---|
江浙沪 | 0 | ¥100 | 免运费 |
江浙沪 | 0 | ¥99.99 | 3% |
大陆其他地区 | 0 | ¥100 | 3% |
大陆其他地区 | 0 | ¥99.99 | 3% |
澳大利亚 | 10% | ¥50 | 5% |
其他国际地区 | 17% | ¥50 | 7% |
你可能注意到后面几个类我已经没有添加field和method了。因为我实在是不确定要加什么东西上去比较合适。
如果一个没有直观的办法被证明是错的,这一定不是一个好的设计,或者至少不是一个好的描述。好的设计激发问题、回答问题、促进沟通、迎接挑战。
每个人打开 https://zenuml.com 自己尝试输入,不要复制粘贴。
当你画出下面任何一个图的时候,你做了这么一件很重要的事情:
你有了一个类,而且它有一个有用的方法 |
PriceCalculator.getTotalPrice(Order) |
Order.getTotalPrice() |
// `ShippingAddress: isJZH, isChina, isAu` <br> // `Order` <br> // FeeCalculator interface // ShippingFeeCal & GstCal<br> // FeeCalculator派生类 sfCal = new ShippingFeeCal() // FeeCalculator派生类 gstCal = new GstCalculator() priceCal = new TotalPriceCalculator(sfCal, gstCal) "priceCal:TotalPriceCalculator".getTotal(Order) { // total = price <br> feeCalculators = from(sfCal, gstCal) forEach("cal as ICalculator in feeCalculators") { ICalculator.cal(Order.price, Order.shippingAddress) } // shippingFee = sfCal.cal(price, shippingAddress) { // if (shippingAddress.isJZH && price > 100) { // fee = Zero() // } else if (shippingAddress.isJZH && price < 100) { // fee = price.multily(0.03) // } else { // //... // } // } // // SRP = Single Responsibility Principle // gst = gstCal.cal(price, shippingAddress) { // if (shippingAddress.isAu) { // gst = price.multiply(0.10) // } else if (!shippingAddress.isChina) { // gst = price.multiply(0.17) // } // } // return price + gst + shippingFee } |