背景
我有一个设计模式问题,我希望有人可以解决。我用PHP编程,但我相信DAO / VO在Java中很流行。
我多年来一直在使用MVC。我设计了一个MVC购物但使用过程式编程。因此,最近我决定使用OO再次开发购物车。
问题:
我遇到的问题是我的Product类没有使用RetrieveAll()方法。 例如。如果我列出了10个产品,我将从哪个实例调用RetrieveAll()方法?我会有10个选择。
解决方案:
因此,我找到了DAO / VO模式。 除非我没有充分研究这种模式 - 我相信每个数据库表必须有一个Model + DAO。没有模型或DAO应该知道另一组模型或DAO。因此被封装。 该模式非常有意义,将数据库层从模型中拉出来。
然而。在购物车中,我的产品被分配了类别。 一类可以是电子产品,服装等。
共有3个表格: - 类别(pid,名称) - 类别项目(iid,名称) - 类别链接(pid,iid)
从MVC方法来看,控制器应该与哪个DAO进行通信是没有意义的?
应该是:
答案 0 :(得分:1)
我不确定VO是什么意思。它是价值对象吗?
我是DDD(域驱动设计)方法的忠实粉丝(尽管我并不认为自己是大师)。在DDD中,您有所谓的 服务 。 服务 是在您的域上运行并返回数据的操作。服务用你的域数据封装操作。
而不是让控制器执行所有域逻辑,比如要检索的项目,要使用的DAO等等(为什么控制器应该关心域?),它应该封装在自己的域内,在DDD中服务中的案例。
因此,例如,您要检索“电子产品”类别的所有类别项目。 你可以写一个看起来像这样的控制器(原谅我,如果代码有无效的语法,为了举例的话):
public function showItemsByCategoryAction($categoryName) {
$categoryId = $categoryDAO->findByName($categoryName);
if(is_null($categoryId)) {
//@TODO error
}
$itemIds = $categoryLinkDAO->getItemsByCategoryId($categoryId);
if(empty($itemIds)) {
//@TODO show error to the user
}
$items = $categoryItemDAO->findManyItems($itemIds);
//@TODO parse, assign to view etc
}
这至少引入了两个问题:
使用“服务”图层,同一个控制器可能看起来像
public function showItemsByCategoryAction($categoryName) {
$service = new Item_CategoryName_Finder_Service();
$items = $service->find($categoryName);
if(empty($items)){
//@TODO show empty page result, redirect or whatever
}
$this->getView()->bind('items', $items);
}
控制器现在干净,小巧,所有Domain逻辑都封装在一个可以在代码中的任何地方重用的服务中。
现在有些人认为控制器应该对DAO一无所知,只使用服务与域通信,其他人说可以从控制器调用DAO,没有严格的规则,决定什么更适合你。
我希望这会对你有所帮助! 祝你好运:)
答案 1 :(得分:1)
我也不是DDD的专家,但这是我的看法。这是应用存储库模式的情况。基本上,域名不知道也不关心DAO或其他任何与之相关的问题。最多了解存储库接口(应该在基础结构级别实现)。
控制器知道域和存储库。存储库封装了与db相关的所有内容,应用程序只知道存储库本身(事实上接口应该是实际的实现应该注入)。然后在存储库中你有DAO然而你认为合适。存储库仅接收和发回应用程序/域对象,与db访问实现无关。
简而言之,db相关的任何内容都是部分内容,它是存储库的实现细节。
答案 2 :(得分:0)
返回类型,因此控制器应该与哪个dao对话:
每个数据实体实现一个DAO类更清晰,
CRUD操作应该进入Dao课程, C-Create,R-Read,U-Update,D-Delete
读取操作与创建,更新,删除不同,大部分时间读取操作在考虑返回时会有不同的风格。
对于Read操作,在决定哪个dao方法应该去哪个dao类时可以考虑返回类型
以下是一些商业实体和Dao
Exchange -> ExchangeDao
Company -> CompanyDao
Stock -> StockDao