原创作者: firebody   阅读:2194次   评论:1条   更新时间:2011-05-26    
如今采用Hibernate实现的Domain Model,多数只是维护实体之间的关联,而大多数的业务逻辑,则是由Service Layer来实现。

这样的模型对象拥有的行为太少了,以至于Martin Fowler给他们下了一个定义:贫血模型。

我们知道,高内聚低耦合是衡量一个模型设计是否合理的重要标准之一。对象组件间合理分工协作可以解决复杂的问题逻辑,按照这个标准,我们似乎可以很自然的各种行为封装到各个模型对象中。 然而,现在绝大多数的应用没有这样做。

ORM作为模型对象与数据库模型之间的接口,它的引入无疑承担了实体领域模型所能称之为领域模型的 所有责任。 正如同Martin Fowler所说的,贫血的领域模型承担了领域模型的所有成本,却没有得到真正的收益。
在这里,真正的收益应该是指高内聚低耦合的拥有复杂对象行为的领域模型,确实,我们设计的领域模型根本没有实现任何的功能,我们只能在外面从新设计一个 Service Layer来管理所有的行为。

我不敢评论这样的设计方案是怎样的不合理。 当设计到拥有比较复杂问题领域模型的时候,这种只负责管理实体间关联关系的实体模型肯定不能适应,这样做的后果就是将复杂领域逻辑统统 移植到 Service Layer层或者胡乱给起名字的一个外层。

考虑Martin Fowler 《Analysis Patterns》中著名的一个通用模型:团体责任模型。里面的约束需要在实体领域模型中得以实现,在贫血领域模型中,封装实现这样的需要检索 验证某个甚至全部实体数据的行为只能移植到Service Layer中。 这样的移植对于领域模型的构架无疑大大增加了复杂度。


那么,我们能不能在贫血领域模型基础上,加入对象行为,使之拥有丰富的行为呢? 我想这是可以解决的,解决的关键是将可访问底层实体数据的行为赋予每一个实体模型对象,最简便的办法就是用一个全局访问点来实现。

考虑这么一个层次:
public interface ServiceProvider{
                public Object getService(String serviceName);;
       
}


public ServiceProviderImpl{
              public ObjectgetService(String serviceName);{
             
                    return ServiceLocator.getService(serbiceName  );;
             }
               
}

public interface CRUD{
     public void save();;
      public void delete();;
       public void load(Long id);;
      public void update();;
}

public Group implements CRUD {

    private String name;
     private List  users;
      public GroupService getGroupService();{
           return (GroupService);getServiceProvider();.getService(this.class.getName();+"Service");
      }
     public void save();{
          if(getGroupService();.findGroupByName(name);!=null);
                       throw new RuntimeExepion("duplicate group name!");;
          getGroupService();.save(this);;
      }
      public  Group load(Long id);{
           this=getGroupService();.load(this.class,id);;
           return this;
      }
      
     public void addUser(user user);{
             
            users.add(user);;
            this.save();; 
     
    }
     public void removeUser(User user);{
     }

     

}


这样作的问题是与建立贫血对象模型相比,领域对象模型的行为通用需要ServiceLayer来完成,约定:
1)ServiceLayer层只负责实现简单的单步骤的与底层数据库访问的 逻辑,不包含任何业务领域逻辑。 如上面的 service.save(),service.update, service.delete , service.findGroupByName.... 

2) 领域模型对象负责对自身的领域逻辑进行封装。

3)通过赋予模型对象行为,建立对象间行为关联,以完成更复杂的 商业逻辑。

4)外层业务逻辑层只能看到领域模型对象,不能直接操作任何的类似Service.save这样的直接访问底层数据库的行为。
评论 共 1 条 请登录后发表评论
1 楼 flyfeifei66 2011-11-13 23:53
"贫血"不一定真的贫,本人就是血多导致血热~~

发表评论

您还没有登录,请您登录后再发表评论

文章信息

Global site tag (gtag.js) - Google Analytics