跨越分析与设计的鸿沟

作者:willem 发表时间:2008年06月18日 13:34 回复此消息回复

原贴网址: http://www.jdon.com:8080/jivejdon/thread/34232.html
标签列表 建模案例(52)      ddd(126)     

如何把分析转化为设计,又如何把设计模式跟域模型结合?
这里边如何还操作,总有章可循.
各位有何高见.现在举个例比较好说明问题.

现有一个库存检查的逻辑:

对A类别的产品: 不需要库存检查,可下单,
对B类别的产品: 一定要库存检查,有库存可下单,无库存不能下单
对C类别的产品:
购买该类别的客户需要选择送货周期,如果
客户要求的送货周期大于30天,是不需要检查库存(即30天后一定可以送货),如果小于30天需
要检查库存.


以后可能还有其它类别的处理逻辑,这里有两处变化.产品类别 以及 该类别的库存处理逻辑.这个似乎,可以用Bridge 模式来解决扩展问题.现在的问题是:如何把这个设计跟原来的模型整合起来. 这个产品类别不知道如何来抽象化.如果用这个设计,那么用这个接口OrderService需要判断产品类别,然后创建不同的处理逻辑.


现有一个大概的设计图:



[该贴被willem于2008-06-18 13:34修改过]

这个主题共有 43 回复 / 31 2 3
回复:跨越分析与设计的鸿沟 发表: 2008年06月18日 15:08 回复
willem 发表文章: 25/ 注册时间: 2008年03月24日 11:34
这些设计类,如果按DDD规则来分层,如何归类呢?

re:跨越分析与设计的鸿沟 发表: 2008年06月18日 16:16 回复
freebox 发表文章: 279/ 注册时间: 2008年03月01日 01:08

abstract class Category{
abstract void accept(CheckStock cs);
}
class ACategory extends Category{
void accept(CheckStock cs){
cs.check(this);
}
}
interface CheckStock{
void check(ACategory a);
void check(BCategory b);
}
class Checker implements CheckStock{...}

不知这样如何,因为我觉得是否检查是Category相关的。
[该贴被freebox于2008-06-18 16:21修改过]

回复:re:跨越分析与设计的鸿沟 发表: 2008年06月18日 17:41 回复
willem 发表文章: 25/ 注册时间: 2008年03月24日 11:34
感觉是Visitor模式. 完全不是 原来 的 Bridge 模式.思考中......


而且Visitor模式有一个不好的地方,如果我的产品类别经常变动,Visitor在这里就要改动.
[该贴被willem于2008-06-18 18:20修改过]

回复:re:跨越分析与设计的鸿沟 发表: 2008年06月18日 18:13 回复
willem 发表文章: 25/ 注册时间: 2008年03月24日 11:34
我想请教freebox ,为什么你想到的是这种设计方案(Visitor模式), 能否把你的思考过程讲一下,谢谢

虽然这些个模式都很熟悉,但老用错,怎么用设计模式总有个章法.比如从哪个方面分析入手等等. 我再比较了一下这两个模式,一个是行为,一个结构. 而上面的逻辑应该是行为. 似乎从设计模式的分类来入手也是一个方面.

re:跨越分析与设计的鸿沟 发表: 2008年06月18日 21:00 回复
freebox 发表文章: 279/ 注册时间: 2008年03月01日 01:08
也许和您所说的原来的Category意义不同,原来的多个Category可能使用同一种检查方案。我的Category拥有“检查方案类别”的意义,就是“不检查、总检查这些,以及等等”。
我也不确定这个方案就是适用的,并且我不知道这就是Visitor模式(不是说您说这是Visitor模式说错了,是我在概念上不清楚),仅仅是觉得应该这样设计。
理由就是您说的检查方案(该类别的库存处理逻辑)和检查方案类别(产品类别或产品类别的集合所具有的检查类别)都有可能变化。
改个名字:

class Category{
CheckKind kind;
}
abstract class CheckKind{
abstract void accept(CheckStock cs);
}
class NeverCheckKind extends CheckKind{
void accept(CheckStock cs){
cs.check(this);
}
}
interface CheckStock{
void check(NeverCheckKind a);
void check(AlwaysCheckKind b);
}
class Checker implements CheckStock{...}

[该贴被freebox于2008-06-18 21:18修改过]

回复:re:跨越分析与设计的鸿沟 发表: 2008年06月19日 10:40 回复
willem 发表文章: 25/ 注册时间: 2008年03月24日 11:34


abstract class CheckKind
{
abstract void accept(CheckStock cs);
}



这个抽出来了,比较好

回复:跨越分析与设计的鸿沟 发表: 2008年06月19日 20:15 回复
banq 发表文章: 9485/ 注册时间: 2002年08月03日 17:08
楼上讨论很不错,Freebox的设计方案看起来还是合适恰当的。

我想补充的是:checkStock绝对不能放入OrderService中,因为checkStock是重要的下单判断标准,属于业务逻辑,根据Evans DDD和充血理论,业务逻辑应该进入领域模型,而不是服务OrderService

Evans DDD中有一个类似案例展示过滤筛选,大概是发票是否过期的判断,根据Domain Model又建立了一个Proxy对象用来封装判断发票是否过期,反正发票是否过期不能进入服务。

回复:回复:跨越分析与设计的鸿沟 发表: 2008年06月20日 08:52 回复
willem 发表文章: 25/ 注册时间: 2008年03月24日 11:34
checkStock放入OrderService中,还是按常用的分层架构套路, 用Proxy,我倒要试试,最终的service层,我想应该是很薄的一层.

回复:回复:回复:跨越分析与设计的鸿沟 发表: 2008年06月20日 13:11 回复
killer 发表文章: 106/ 注册时间: 2007年07月17日 15:40
checkStock不能放入OrderService,要坚持静态决定动态的原则。下面贴一下我的设计,不足之处,请大家指正,共同讨论改进。
//订单
public class Order implements Serializable {

private String No;
private List<OrderItem> items;


//检查库存是否足够
public boolean checkStorage(){
boolean result = false;
for (Iterator itr = items.iterator(); itr.hasNext();){
OrderItem item = (OrderItem)itr.next();
result = item.IsStorageEnough();
if (!result){
break;
}
}
return result;
}
}

//订单项
public class OrderItem implements Serializable {

private String No; //序号
private Product product; //产品
private Double qty; //数量
private long deliveryPeriod; //送货周期

//检查库存是否足够
public boolean IsStorageEnough(){
ICheckStorage checker = null;
if (product.getCategory().getCode().equals("A")){
checker = new ACheckStorage();
}
else if (product.getCategory().getCode().equals("B")){
checker = new BCheckStorage();
}
else if (product.getCategory().getCode().equals("C")){
if (deliveryPeriod > 30){
checker = new ACheckStorage();
}else checker = new CCheckStorage();
}

return checker.checkStorage(product, qty);
};
}

//订单仓储
public class OrderRepository {
public void save(Order order){

}
}

//产品
public class Product implements Serializable {

private String ID;
private String code;
private ProductCategory category;
}

//产品类别
public class ProductCategory implements Serializable {

private String ID;
private String code;
}

//检查库存接口
public interface ICheckStorage {

public boolean checkStorage(Product product, Double qty);

}

public class ACheckStorage implements ICheckStorage {}
public class BCheckStorage implements ICheckStorage {}
public class CCheckStorage implements ICheckStorage {}




//订单服务
public class OrderService {

OrderRepository ordRepstry;

//下单
public void dispatchOrder(Order order){
if (order.checkStorage()){
//to do 设置订单状态为“下达”等操作
ordRepstry.save(order);
}
}

public OrderService(OrderRepository ordRepstry) {
super();
this.ordRepstry = ordRepstry;
}

}


re:跨越分析与设计的鸿沟 发表: 2008年06月20日 13:17 回复
freebox 发表文章: 279/ 注册时间: 2008年03月01日 01:08
OrderService是repository?只是取了这么个名字吧?

回复:re:跨越分析与设计的鸿沟 发表: 2008年06月20日 14:06 回复
killer 发表文章: 106/ 注册时间: 2007年07月17日 15:40
>>>OrderService是repository?只是取了这么个名字吧?
OrderService肯定不是repository啊,两者的角色定位不一样。

re:跨越分析与设计的鸿沟 发表: 2008年06月20日 14:51 回复
freebox 发表文章: 279/ 注册时间: 2008年03月01日 01:08
我的设计在附件里,望大家批评指正。
我的意思是楼主图中的OrderService,因为我发上帖的时候还没有看到您的帖子,非常抱歉。
model.rar


model.rar

回复:re:跨越分析与设计的鸿沟 发表: 2008年06月20日 15:24 回复
willem 发表文章: 25/ 注册时间: 2008年03月24日 11:34
killer 明确了各个类的责任,赞同,但设计上我还是比较喜欢freebox 的设计, 不喜欢一堆的if-else.
在各个层传递数据时, 喜欢POJO, 所以可以再用一个类和POJO结合而达到一个所谓的充血实体.比如用代理,装饰等可以做到.



[该贴被willem于2008-06-20 15:26修改过]

re:跨越分析与设计的鸿沟 发表: 2008年06月20日 16:26 回复
freebox 发表文章: 279/ 注册时间: 2008年03月01日 01:08

final class Checkers{
private Checkers(){}
public static ICheckStorage getChecker(OrderItem item){
String code=item.getProduct().getCategory().getCode();
ICheckStorage checker=new DefaultStorage();
if ("A".equals(code)){
checker = new ACheckStorage();
}
else if (
"B".equals(code)){
checker = new BCheckStorage();
}
else if (
"C".equals(code)){
if (item.getDeliveryPeriod() > 30){
checker = new ACheckStorage();
}else{
checker = new CCheckStorage();
}
}
return checker;
}
}
public class OrderItem implements Serializable {
private String No;
//序号
private Product product;
//产品
private Double qty;
//数量
private long deliveryPeriod;
//送货周期

//检查库存是否足够
public boolean isStorageEnough(){
return Checkers.getChecker(this).checkStorage(product, qty);
}
}

略作部分修改,望继续讨论。
上传的附件怎么下载不了呢?是不是[url]里?后面的没解释出来?
这是用上传功能上传的。
model.rar
这是编辑时显示的url,直接拿出来了。
http://www.jdon.com/jivejdon/uploadDL.jsp?type="application/octet-stream&dlname=model.rar&id=173
[该贴被freebox于2008-06-21 09:36修改过]
model.rar

这个主题共有 43 回复 / 31 2 3
 
上一篇: 设计模式学习历程 下一篇: DDD中Factory和Reposito..
 
查询本论坛 最热门帖子

热点Tag: AOP cache 缓存 DDD EJB 集群 设计模式 Hibernate IOC JiveJdon OO RBAC Seam Spring Struts

标签总列表


Jdon框架演示

JiveJdon3.0
源码下载

GoF设计模式

在线教程

社区精彩讨论




google yahoo 新浪ViVi 365Key网摘 天极网摘 CSDN网摘 添加到百度搜藏 POCO网摘 博采网摘





手机阅读 add to google add to yahoo
联系我们 | 关于我们 | RSS订阅 | 广告联系 | 网站地图
Copyright (C) 2002-2008 Jdon.com, All Rights Reserved 版权所有 上海解道计算机技术有限公司
沪ICP备05018152号 如有意见请与我们联系 Powered by JdonFramework