简体   繁体   English

服务和DAO始终实现接口

[英]Service and DAO always implement interfaces

In all the MVC projects I've seen, "service" and "DAO" classes always implemented their own interfaces. 在我看到的所有MVC项目中,“服务”和“ DAO”类始终实现自己的接口。 But almost all the times, I haven't seen a situation in which having this interface has been useful. 但是几乎所有时候,我都没有看到过使用该接口的情况。

Is there any reason to use interfaces in these cases? 在这种情况下是否有任何使用接口的理由? What may be the consequence of not using interfaces in "service" and "DAO" classes? 在“服务”和“ DAO”类中不使用接口可能会有什么后果? I can't imagine any consequences. 我无法想象任何后果。

Spring is an Inversion of Control container. Spring是一个Inversion of Control容器。 This, in one sense, means that the implementation of classes you use doesn't fall on the application but on its configuration. 从某种意义上讲,这意味着您使用的类的实现并不取决于应用程序,而取决于其配置。 If you have a class that needs a UserRepository to store User instances, it'd be something like 如果您有一个需要UserRepository来存储User实例的类,它将类似于

class UserService {
    @Autowired
    private UserRepository userRepository;
}

interface UserRepository {
    List<User> getUsers();
    User findUserBySIN(String SIN);
    List<User> getUsersInCountry(Long couyntryId);
}

And you would have a bean declared for it 然后您将为此声明一个bean

<bean class="com.myapp.UserRepositoryHibernateImpl">
   ...
</bean>

Notice this bean is UserRepositoryHibernateImpl which would implement UserRepository . 注意,这个bean是UserRepositoryHibernateImpl ,它将实现UserRepository

At some point in the future of the world, the Hibernate project stops being supported and you really need a feature that is only available on Mybatis so you need to change implementations. 在将来的某个时候,Hibernate项目将不再受支持,您确实需要仅在Mybatis上可用的功能,因此您需要更改实现。 Because your UserService class is using a UserRepository declared with the interface type, only the methods visible on the interface are visible to the class. 因为您的UserService类正在使用用接口类型声明的UserRepository ,所以该类仅可见接口上可见的方法。 So changing the actual polymorphic type of userRepository doesn't affect the rest of the client code. 因此,更改userRepository的实际多态类型不会影响其余的客户端代码。 All you need to change (excluding creating the new class) is 您需要更改的所有内容(不包括创建新类)是

<bean class="com.myapp.future.UserRepositoryMyBatisImpl">
   ...
</bean>

and your application still works. 并且您的应用程序仍然有效。

There are lots of arguments in favour of interfaces, see Google. 有很多支持接口的论点,请参见Google。

I can added to the points other people mentioned: 我可以补充其他人提到的几点:

  1. Imagine you change your DAO implementations from Hibernate to iBatis. 想象一下,您将DAO实现从Hibernate更改为iBatis。 Dependency to interface rather than implementation would be a great help for the service layer. 依赖接口而不是实现将对服务层有很大帮助。
  2. If you use AOP or proxies using JDK dynamic proxies then your classes must implement interfaces. 如果您使用AOP或使用JDK动态代理的代理,则您的类必须实现接口。 This is not the case for CGLIB. CGLIB并非如此。
  3. In the service layer if you want to release your methods to other clients to call, giving them "interface as a contract" would make more sense rather than implementations. 在服务层中,如果您希望将方法释放给其他客户端以进行调用,那么给它们“作为契约的接口”将比实现更有意义。
  4. If you ever want to separate services.jar from daos.jar then having interfaces on your daos would save the services.jar from recompile in case daos.jar changes. 如果您要从daos.jar分离services.jar,则在daos上具有接口可以避免在daos.jar发生更改时重新编译services.jar。

In short, it is just good to have interfaces! 简而言之,拥有接口就很好!

The interface-based implementation helps in mocking them in the test suite. 基于接口的实现有助于在测试套件中模拟它们。 In our project, while testing the service layer, we mock the DAOs and provide hard coded data instead of really connecting to the DB. 在我们的项目中,测试服务层时,我们模拟DAO并提供硬编码数据,而不是真正连接到DB。 The same argument applies to service layer as well. 同样的论点也适用于服务层。

尽早使用接口可以使您的应用程序具有可伸缩性,并且不使用接口的后果就是牺牲了应用程序的可伸缩性。

I've been asking myself the exact same question recently, feeling that creating an interface even if I know there's ever going to be a single implementing class is silly and adds to the bloat (every Java programmer who tried a more pragmatic language will know the feeling). 我最近一直在问自己一个完全相同的问题,觉得即使我知道将永远只有一个实现类,创建一个接口也是很愚蠢的,并且使人adds肿(每个尝试使用更实用的语言的Java程序员都会知道这个问题)。感觉)。 That's yet another compilation module, often only created to satisfy one's inner dogmatist. 那是另一个编译模块,通常只是为了满足一个人的内心教条主义者而创建的。

Spring seems to have evolved into a module/component oriented framework where the programmer only creates the blocks and the framework assembles it all together. Spring似乎已经发展成为面向模块/组件的框架,程序员只在其中创建块,然后框架将它们组装在一起。 This is why having more than one bean matching the criteria is a problem and complicates things (you end up using qualifiers which kind of kill the purpose of DI). 这就是为什么要有多个与条件匹配的bean成为一个问题,并使事情变得复杂的原因(最终使用限定符会破坏DI的目的)。 Programmers will naturally try to avoid type ambiguities to minimise amount of required configuration, ideally making any given block fit into only one "slot". 程序员自然会尝试避免类型歧义,以最大程度地减少所需配置的数量,理想情况下,使任何给定的块仅适合一个“插槽”。

In my opinion, DI's biggest advantage is not that it makes it easy to change implementations (by simply changing type of declared class in the config XML), but that it allows easier separation of dependencies, thus making it easier to test each component in separation. 在我看来,DI的最大优点不是 (通过简单地更改config XML中声明的类的类型)使实现的更改变得容易,而是使依赖关系的分离更加容易,从而使每个组件的分离测试更加容易。 。 You don't need one-child interfaces for that. 您不需要一个孩子的接口。

Since reverse-engineering a class to extract its interface would be a purely mechanical task, I wouldn't worry about "what if I need to add another implementation?" 由于对类进行逆向工程以提取其接口将是纯粹的机械任务,因此我不必担心“如果我需要添加另一个实现会怎样?” argument. 论点。

Disclaimer : opinion of a small-to-mid applications developer; 免责声明 :中小型应用程序开发人员的意见; I'm sure the situation changes with large projects. 我相信大型项目的情况会有所变化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM