代码之家  ›  专栏  ›  技术社区  ›  Boden

将DAO隐藏在服务背后,为什么?

  •  3
  • Boden  · 技术社区  · 17 年前

    在回顾了大量MVC风格的web应用程序之后,我注意到在业务层前面有一个非常大的服务接口是很常见的。该接口的实现通常包括一组DAO。所以你有这样的想法:

    public class FoodServiceImpl implements FoodService {
    
      private FruitDAO fruitDAO;
      private VegetableDAO vegetableDAO;
      private MeatDAO meatDAO;
    
      // ... DAO injection stuff
    
      public List<Meat> getMeat() {
        return meatDAO.getMeat();
      }
    
      public void addMeat(Meat meat) {
        meatDAO.add(meat);  
      }
    
      public List<Fruit> getFruit() {
        return fruitDAO.getFruit();
      }
    
      // ... tons of methods that mostly just delegate to DAOs
    
    }
    

    假设您的DAO一开始不是具体的,为什么不将DAO公开到下一个级别呢?

    因此,不是:

    // assume foodService is injected at runtime
    public void controllerMethod() {
      foodService.getFruit();
      foodService.getMeat();
    }
    

    你只是

    // assume DAOs are injected at runtime
    public void controllerMethod() {
      fruitDAO.getFruit();
      meatDAO.getMeat();
    }
    

    一方面,将应用程序的全部内容封装在一个接口中看起来有点不错。。。。另一方面,您可以得到一个巨大的接口,它的实现只不过是委托给DAO。

    在启动web应用程序时,这是一种“最佳实践”,还是仅在需要某种程度和类型的复杂性时才适用?

    5 回复  |  直到 17 年前
        1
  •  8
  •   duffymo    17 年前

    我认为注入服务层更有意义,因为它知道工作单元。如果您的用例需要多个DAO参与一个工作单元,则需要一个服务来“拥有”事务。

    此外,它是面向服务架构的本质。忘掉WS-*;服务映射到用例和业务流程。

        2
  •  6
  •   cliff.meyers    17 年前

    假设整个后端不仅仅是一个巨大的CRUDAPI,您将经常看到在服务层调用业务逻辑。业务逻辑可能直接在服务方法本身中(也称为“贫血域模型”),或者服务层必须只负责调用传递给DAO层的实体上的业务方法(“富域模型”)。您可能还会看到在服务层中进行的安全性或审计等工作。或者,可以通过面向方面编程(AOP)将交叉关注点(如安全性或审计)应用于服务层。

        3
  •  3
  •   Charlie Martin    17 年前

    创建类只有一个原因:在固定边界后面隐藏一些实现细节等。在本例中,您有一个名为FoodService的服务和一个了解各种DAO的实现类。你在隐瞒什么?

    1. 事实上,你有这些种类的食物
    2. 它们的储存方式。

    如果它们的存储方式永远不会改变,那么您可能不需要这个。但是如果您的DAO被一种不同的机制所取代——比如分布式的Google BigTable——您可能更愿意不需要修改所有的代码类型。

    当然,你总是有机会开始携带健康和美容用品,因此需要另一门课程。(事实上,如果有一个方法可以告诉您可以访问哪些类型的内容,然后有一个方法可以访问给定类型的内容,这不是更好吗?)

        4
  •  2
  •   GClaramunt    17 年前

    MVC主要是一种表示模式,大多数非平凡系统使用分层方法,其中至少有表示层、业务层和数据访问层。在您的情况下,您可以直接暴露DAOS,但在中间保持业务层可以更好地封装业务逻辑并有助于系统扩展性。假设您对肉的存放位置有新的要求:

    if (meat.expirationDate-today >= 5 days)
       FridgeDAO.store(meat)
    else if (meat.expirationDate-today <5 days)
       FreezerDAO.store(meat)
    else 
       discard(meat)
    

        5
  •  0
  •   Archimedes Trajano    16 年前

    做远程处理的最好方法是根本不做远程处理。

    请记住,从整体上看,程序员的时间比硬件花费的更多。