精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2004-04-26
举一个例子, 系统需要列出某个Group下面某种类型的User, 那么就有这样的UserService interface: public interface UserService { public User[] listUsersByType(Group group, String userType);; } 实现: public class UserServiceImpl implements UserService { private QueryManager qm; public UserServiceImpl(QueryManager qm); { this.qm = qm; } public User[] listUsersByType(Group group, String userType); { return qm.findUsersByType(group, userType);; } } public interface QueryManager { public User[] findUsersByType(Group group, String userType);; } public class QueryManagerImpl implements QueryManager { public User[] findUsersByType(Group group, String userType); { //"select * from user where user.group = :group and userType = :userType"; //... } } 我的想法是listUsersByType这种方法为什么不写在Group这个Domain Object里面呢: public interface Group { public User[] getUsersByType(String userType);; } public class GroupImpl implements Group { public User[] getUsersByType(String userType); { return qm.findUsersByType(this, userType);; } } 这样代码就简化了很多了, 而且从面向对象的设计角度来看, listUsersByType应该是属于Group的一个自发的行为, 而不应该是有一个Service来做处理. 这样来使用Facade Service + 简单的domain object, 感觉和面向数据结构的设计其实没有多少区别. 一些可以应用在domain object上的模式也都会受到很大的限制, 不知道大家的系统设计是否也是这样么? 是否我陷入了什么误区? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2004-04-26
我想他们这样做主要是处于灵活性的考虑。使用一个 Facard,就不用和 QueryManager 绑得太死了,以后还可以换成其它的实现。而且这类业务可能会有很多个类,统一放在 Facard 这个类中访问也便于管理。
这是我所能想到的两个好处,也是 Facrd 的典型作用。Facard 真的没有什么神秘的。 |
|
返回顶楼 | |
发表时间:2004-04-26
没有人 写道 我想他们这样做主要是处于灵活性的考虑。就不用和 QueryManager 绑得太死了,以后还可以换成其它的实现
我正是看不懂第一种写法和第2种相比在灵活方面有什么优越性,才感到疑惑。QueryManager是一个interface,要换其他实现也应该是换QueryManager的实现,而不用去换Service的实现吧? 而且从面向对象的设计的想法来看, 这些方法不应该在这种Service里面出现呀。再举一个例子: public interface AuthService { public User login(String loginId, String password);; } 这种验证的Service,看过很多项目都是这样写的。但是如果从面向对象的设计想法来看, 登陆这个动作应该是属于某个匿名的Visit domain object,而不是某个Service做的,设计成为 public interface AnonymousVisit extends Visit { public User login(String loginId, String password);; } 不是更加符合OO的想法吗? |
|
返回顶楼 | |
发表时间:2004-04-26
我不太清楚你说的 domain object 的含义,你能解释一下吗?
如果从名字上看,这个 Facard 确实就是 Facard 模式的话,那么它的作用就是我说的提供一个统一访问的接口,没有多少深意。别想太多,老外的想法其实比我们直接的多。 |
|
返回顶楼 | |
发表时间:2004-04-26
纠正一点:Facade模式, 不是Facard
解释一下我对于domain object的理解: Domain Object是业务对象,是相对系统的架构对象来说的。 比如一个系统里面的CacheManager, PersistManager这些是和业务无关的架构对象,domain object就是User, Group, Order等等这些业务对象。 我的疑惑在于把这些方法放在Facade Service里面符合OO设计的职责分明的原则吗?为什么大家都这样做呢? |
|
返回顶楼 | |
发表时间:2004-04-26
抱歉啊,写错了。
那么你认为 service 与 domain object 应该是两种职责了。你认为 service 里面应该实现什么职责呢? |
|
返回顶楼 | |
发表时间:2004-04-26
我觉得service可以更高级别的抽象, 一个单独的服务
domain object 最多只能到组件级别 , |
|
返回顶楼 | |
发表时间:2004-04-26
我觉得用DomainObject更好。
这样复用性更强。尤其是和Domain有one-to-many等关系的,可以直接由DomainObject得到DomainObject的方法,更是应该写入到DomainObject中。例如user.getGroup()等 而Service作为一种提供user本身不具备的能力例如删除,检索,创造等而存在。 Service和DomainObject之间最多有个Dao,而不应该有什么Manager或者Handler。 至于Action是否调用一个ServiceFacade,这个可有可无。如果觉得直接从struts或webwork的Action调用Service是不好的事情,也可以考虑做个Facade。 关键是,不能出现万能的上帝对象和只有数据的DomainObject (以上这些是刚从potian取来的经,详情请看我blog) |
|
返回顶楼 | |
发表时间:2004-04-27
我觉得很重要的一点也许在于怎样判断一个东西是不是业务模型本身
比如这两个, 也许一般都认为是属于user的了, 如果没有ORM这两个肯定也是要调用持久的, 也许就不一定这样直接写对象关系了 user.getGroup(); user.getRole(); 下面的关系不一定会加到user了, 加上这个user类就不能复用到不处理订单情况了. user.getOrders(); 而下面的行为就更罕见了 user.register(); // 用户注册到系统 user.login(); // 用户登陆系统 user.logout(); // 用户注销登陆 user.update(); // 用户更新资料 user.query(..); // 用户查询相关用户 用户对象自身已经包含了CUD操作, 而如果这些操作, user只能算是个数据而已. 当然用户本身也是一个有状态的对象了, 只有在某种状态下才能执行一些操作(比如登陆后), 这也是个状态模式了. 如果用户登陆的话应该写成这样: user.setName(..); user.setPassword(..); user.login(); 我想这些东西都按照quake wang的看法可以算着用户在这个系统仅仅用户模块扮演角色的本质行为吧, 甚至更多的东西都可以用户为主体, 只要可以用它做主语发出一个行为. 但这个在OO上也许会有点麻烦吧, 在一个类中放置太多的东西, 是否违反了SRP, 除非用AOP分离不同方面. |
|
返回顶楼 | |
发表时间:2004-04-27
冰云 写道 尤其是和Domain有one-to-many等关系的,可以直接由DomainObject得到DomainObject的方法,更是应该写入到DomainObject中。例如user.getGroup()等 对于getGroup(), getUser()这些简单的get reference方法我都是写在Domain Object, 我想不会有人写成UserService.getGroup(User user) 这样来用吧? 但是我看到稍微复杂一些逻辑的代码, 比如User加入某个Group, 用 User.joinGroup(Group group); 还是用 UserService.addUserToGroup(User user, Group group); 这个是否值得讨论? 或许仅仅是语义上的区别? 前者是User自发的加入某个Group的行为, 而后者是管理员添加User加入Group行为? UltraFool 写道 下面的关系不一定会加到user了, 加上这个user类就不能复用到不处理订单情况了. user.getOrders(); Yes, 就是这个意思了, 再比如下订单这个动作: User.placeOrder, 会放到Service里面, 写成OrderService.placeOrder. 还有一种情况是虽然是某个业务对象必然拥有的业务逻辑, 但是由于牵涉到多个domain object, 为了保持一个thin domain object, 我也会写在Service里面. UltraFool 写道 而下面的行为就更罕见了 user.register(); // 用户注册到系统 user.login(); // 用户登陆系统 user.logout(); // 用户注销登陆 user.update(); // 用户更新资料 user.query(..); // 用户查询相关用户 你误解我的想法了, 这些行为应该是一个Visit obejct (系统访问对象), 所拥有的, 比如login是AnonymousVisit的行为, 而logout就是NamedVisit的行为. 另外CRUD这些方法我还是写在Service对象里面. 感觉这些业务代码应该在Domain Object和Service之间应该有一个分布原则, 不知道大家的实践是怎么样的. |
|
返回顶楼 | |