为什么在服务和dao层中总是有单一的实现接口?

我曾经/看过几个Spring-hibernate Web应用程序项目,它们具有与实际服务和dao类相同的接口。

我一直认为这两个是拥有这些单一实现接口的主要原因:

  • Spring可以将实际实现作为给定类中的依赖关系(松耦合)

    public class Person { 
        @Autowired 
        private Address address;
    
        @Autowired 
        private AccountDetail accountDetail;
    
        public Person(Address address, AccountDetail accountDetail) 
        { // constructor
    
  • 单元测试时,我可以创建模拟类并单独测试一个类。

    Address mockedAddress = mock(Address);
    AccountDetail mockedAccountDetail = mock(AccountDetail);
    Person underTestPerson = new Person(mockedAddress, mockedAccountDetail); 
    // unit test follows
    
  • 但是,最近我意识到:

    Spring可以将具体实现类作为依赖关系进行连接:

    public class Person { 
    
    @Autowired 
    private AddressImpl address;
    
    @Autowired 
    private AccountDetailImpl accountDetail;
    
    public Person(AddressImpl address, AccountDetailImpl accountDetail) { 
    // constructor
    

    像EasyMock这样的模拟框架也可以模拟具体的类

    AddressImpl mockedAddress = mock(AddressImpl);
    AccountDetailImpl mockedAccountDetail = mock(AccountDetailImpl);
    Person underTestPerson = new Person(mockedAddress, mockedAccountDetail); 
    // unit test follows
    

    另外,根据本次讨论,我认为总结是在单个应用程序中,接口大多会被滥用,可能超出惯例或习惯。 当我们与另一个应用程序接口时,它们通常是最有意义的,例如全球许多应用程序使用的slf4j。 在一个应用中,一个类几乎和接口一样是一个抽象。

    所以,我的问题是为什么我们仍然需要接口,然后像* ServiceImpl和* DaoImpl类一样实现单一实现,并且不必要地增加了我们的代码库大小。 模拟具体课程中有没有我不知道的问题。

    每当我和我的队友们讨论这个问题时,我所得到的答案就是,基于接口实现服务和dao类是每个人都遵循的设计 - 他们提到了春季最佳实践,OOP,DDD等等。但是我仍然没有在一个孤立的应用程序中拥有如此多的接口后,得到一个实用的理由。


    接口有更多的优点 - 和代理一样。 如果您的类实现了一个接口,则AOP默认使用JDK动态代理。 如果直接使用这些实现,那么您将被迫使用proxy-target-class = true来使用C​​GLIB代理。 这些需要与JDK代理不同的字节码操作。

    在这里阅读更多。

    请阅读另一个讨论,了解使用接口(Java EE或Spring和JPA)获取更多信息的原因。


    这是一个非常有争议的话题。 简而言之,至少对于您来说,开发者是没有的。

    在EJB2世界中,家庭和远程接口是必须的,并且正是出于@AravindA提及的代理的原因。 安全性,远程处理,池化等都可以封装在代理中,并严格在标准库中提供所需的服务(如DynamicProxy )。

    现在我们有了javaassistcglib ,Spring(如果您愿意的话,可以使用Hibernate,EJB3)完全可以像框架开发人员喜欢的那样检测您的类。 问题是,他们所做的是一件非常烦人的事情:他们通常会要求您添加一个无参数的构造函数。 - 等等,我在这里有参数吗?-Nevermind,只需添加构造函数。

    所以界面在这里保持你的理智。 尽管如此,奇怪的是,具有适当构造函数的类的无参构造函数对我来说并不合适,对吧? 原来(我应该读过规范,我知道)Spring创建了一个功能等同于你的类的接口:一个没有(或被忽略)状态并覆盖所有方法的实例。 所以你有一个“真实”的实例,一个“假接口”,以及假接口的功能,它为你提供所有的安全/事务/远程技术。 不错,但很难理解,如果你没有把它分开,看起来像一个bug。

    而且,如果你碰巧在你的类中实现了一个接口,(至少某些版本的)Spring突然决定你只是代理这个接口,并且这个应用程序无法正常工作。

    因此,迄今为止的原因是,安全和理智。 有理由说这是一种好的做法 - 但是从你的帖子来看,我看到你已经阅读了所有这些内容。 我今天看到的最重要的原因是WTH /分钟度量,特别是如果我们正在谈论项目的新手。

    链接地址: http://www.djcxy.com/p/87893.html

    上一篇: Why always have single implementation interfaces in service and dao layers?

    下一篇: What's the difference between interface and @interface in java?