Java 道场与服务模式

Java 道场与服务模式,java,design-patterns,web,dao,Java,Design Patterns,Web,Dao,我只想扩展一下本教程 我想介绍UserService(接口)、JdbcUserService(类)和类似的服务及其实现 1) 现在,我应该在一个地方放置一个DAOFactory实例并从所有这些服务中使用它,还是应该在每个服务中实例化DAOFactory。如何为服务的每个方法编写测试 2) 如何删除硬编码,如DAOFactory.getInstance(“javabase.jdbc”)并在整个应用程序中执行此设置一次 3) 另外,从web应用程序的角度(多线程)来看,可能的更改是什么 您可能应该使

我只想扩展一下本教程

我想介绍UserService(接口)、JdbcUserService(类)和类似的服务及其实现

1) 现在,我应该在一个地方放置一个DAOFactory实例并从所有这些服务中使用它,还是应该在每个服务中实例化DAOFactory。如何为服务的每个方法编写测试

2) 如何删除硬编码,如
DAOFactory.getInstance(“javabase.jdbc”)
并在整个应用程序中执行此设置一次

3) 另外,从web应用程序的角度(多线程)来看,可能的更改是什么

  • 您可能应该使用一个公共工厂来创建所有DB access类,因为它们将是相关类的“家族”。为工厂创建一个接口,然后创建一个使用DAO实现类的实现。通过这种方式,您可以将系统更改为使用其他方式存储数据,或者模拟数据进行测试
  • 使用factory类隐藏此实现详细信息。此外,如果可能的话,您不应该公开原始DAO对象。最好为“person”和“work function”之类的东西创建一个有限的接口,它只公开您需要的方法,甚至可能在DAO方法的更高级别上。同样,这允许您隐藏细节并在以后更改存储的实现(或用于测试/模拟)
  • 将同步添加到工厂生成的类中。您需要决定amodel,但最简单的方法是首先同步所有方法,然后在需要更高性能时放松锁
  • 另外:您可能希望使用“Singleton”模式来确保只创建一个DAOFactory类的实例

    所以像这样的

    请注意,我的“Singleton”并没有强制执行Singleton原则。它只是用来作为目前使用的到达工厂的常用方式

    interface Person {
      String getName();
      void setName();
    }
    
    interface PersonStorage {
      Collection<Person> getPersonsByName(final String name);
    }
    
    class DAOPerson implements Person {
    
      public synchronized String getName() {
        // Implementation here 
      }
    
      public synchronized void setName() {
        // Implementation here
      }
    
    }
    
    interface Factory {
      PersonFactory getPersonFactory();
    }
    
    class DAOPersonFactory implements PersonFactory {
      // Implementation
    }
    
    class DAOFactory implements Factory {
    
      PersonFactory getPersonFactory() {
        DAOPersonFactory res = new DAOPersonFactory();
        // Set up the instance, probably connect it to the underlying DAO
        return res;   
      }
    }
    
    class FactorySingleton {
      private Factory fac;
    
      FactorySingleton(final Factory implementation) {
        this.fac = implementation;
      }
    
      Factory getFactory() {
        return fac;
      }    
    
    }
    
    接口人{
    字符串getName();
    void setName();
    }
    接口个人存储{
    集合getPersonsByName(最终字符串名称);
    }
    类DAOPerson实现Person{
    公共同步字符串getName(){
    //在这里实现
    }
    公共同步的void setName(){
    //在这里实现
    }
    }
    接口工厂{
    PersonFactory getPersonFactory();
    }
    类DAOPersonFactory实现PersonFactory{
    //实施
    }
    类DAOFactory实现工厂{
    PersonFactory getPersonFactory(){
    DAOPersonFactory res=新的DAOPersonFactory();
    //设置实例,可能将其连接到基础DAO
    返回res;
    }
    }
    类工厂单例{
    私人工厂工厂;
    FactorySingleton(最终工厂实施){
    this.fac=实现;
    }
    工厂getFactory(){
    返回fac;
    }    
    }
    
    让类解析(在内部,而不是通过构造函数或setter)它们的依赖关系通常是一种测试能力。举个例子,如果你有一个类a的复杂依赖项,并且为了测试的目的想要模拟它,因为依赖项本身是由类解析的,你将不能使用模拟(除非你修改了类a逻辑,这本身就是另一个糟糕的测试实践)。对测试能力的关注无疑是导致依赖注入在开发人员中广泛流行的因素之一

    如果您使用依赖注入容器(例如Spring或jboss weld…),那么您的工厂将是一个由您的容器管理的bean。您可以将其范围定义为Singleton,这与跨服务层类共享同一实例的需要相对应


    在测试时,您可以轻松地调整依赖项容器,为您提供一个模拟实例,以简化测试。

    我有点困惑,为什么您的服务类的实现要适应数据库访问策略(jdbc)。您的服务实际上是DAOs吗?如果不是,为什么不让你的服务依赖于接口而不是实现?@yechabbi你是对的,我只需要做一个服务实现。现在,在何处实例化DAOFactory实例,以便在服务之间实现最佳共享。一个简单的JSP/Servlet应用程序的框架示例将回答我所有的问题。我向您发布了一个基于控制反转(依赖注入)设计原则的解决方案。实际上,我想用简单的web应用程序来实现它。我已经看到了这个使用Spring的设计,并尝试在没有DI的情况下用简单的术语进行复制。我认为这是正确的。谢谢你的帮助。然而,我希望通过一个简单的servlet/jsp应用程序获得尽可能好的设计。