带DAO / VO的MVC - Controller应该与哪个DAO通信?

时间:2012-02-25 00:39:07

标签: java php design-patterns

背景

我有一个设计模式问题,我希望有人可以解决。我用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进行通信是没有意义的?

应该是:

  • 控制器与所有3个DAO进行通信,然后将相应的数据结构返回给View?
  • 或者DAO是否应该以某种方式(以某种方式)与单一结构对话并将其返回给控制器?

Please see here for example (image)

3 个答案:

答案 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
}

这至少引入了两个问题:

  1. 控制器是FSUC(胖愚蠢丑陋的控制器)
  2. 代码不可重复使用。如果你想添加另一个表示层(比如开发人员的API,网站的移动版本等),你必须复制粘贴相同的代码(期望视图渲染的部分),最终你会来将封装此代码的东西,这就是服务的用途。
  3. 使用“服务”图层,同一个控制器可能看起来像

    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类时,可以考虑

返回类型,因此控制器应该与哪个dao对话:

每个数据实体实现一个DAO类更清晰,

CRUD操作应该进入Dao课程, C-Create,R-Read,U-Update,D-Delete

读取操作与创建,更新,删除不同,大部分时间读取操作在考虑返回时会有不同的风格。

对于Read操作,在决定哪个dao方法应该去哪个dao类时可以考虑返回类型

以下是一些商业实体和Dao

Exchange -> ExchangeDao
Company -> CompanyDao
Stock -> StockDao
相关问题