跨越分析与设计的鸿沟

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

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

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


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


现有一个大概的设计图:



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

这些设计类,如果按DDD规则来分层,如何归类呢?


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修改过]

感觉是Visitor模式. 完全不是 原来 的 Bridge 模式.思考中......


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

我想请教freebox ,为什么你想到的是这种设计方案(Visitor模式), 能否把你的思考过程讲一下,谢谢

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

也许和您所说的原来的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修改过]



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


这个抽出来了,比较好

楼上讨论很不错,Freebox的设计方案看起来还是合适恰当的。

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

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

checkStock放入OrderService中,还是按常用的分层架构套路, 用Proxy,我倒要试试,最终的service层,我想应该是很薄的一层.

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

}


OrderService是repository?只是取了这么个名字吧?

>>>OrderService是repository?只是取了这么个名字吧?
OrderService肯定不是repository啊,两者的角色定位不一样。

我的设计在附件里,望大家批评指正。
我的意思是楼主图中的OrderService,因为我发上帖的时候还没有看到您的帖子,非常抱歉。
model.rar


attachment:


model.rar

killer 明确了各个类的责任,赞同,但设计上我还是比较喜欢freebox 的设计, 不喜欢一堆的if-else.
在各个层传递数据时, 喜欢POJO, 所以可以再用一个类和POJO结合而达到一个所谓的充血实体.比如用代理,装饰等可以做到.



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


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修改过]
attachment:

model.rar