java 解耦

[…]耦合(或依赖性)是每个程序模块依赖于其他模块中每个模块的程度。

—维基百科

http://en.wikipedia.org/wiki/Coupling_(computer_science)

在面向对象的编程中,删除依赖关系是通过使用接口来完成的。 因此,如果类A依赖于类B,我们将引入接口C,该接口C由B实现。现在A依赖于C(请参见下文)。


android hilt 解耦 java中的解耦是什么意思_java

解耦的第一步称为通过接口编程 。 无论如何,我们仍然必须通过C接口“馈送”类A,无论是B对象还是实现C的任何实例。因此,我们需要此类的实例。 在标准代码中,类A以这种方式实例化B:

publicclassA{
    privateCc=newB();
}

噢亲爱的! 看来我们又从A到B引入了依赖性...希望这个问题有答案,即依赖性注入 。 在依赖关系注入中,一个外部模块负责实例化和设置类B的对象。代码如下:

publicclassA{

    privateCc;

    publicvoidsetC(Cc){
        this.c=c;
    }
}

DI框架创建一个新的B并将其通过setter传递给A对象:它是唯一知道B类(并因此而依赖)B的组件。尽管如今,DI显然已经成为主流,但很大程度上要归功于Spring框架 ,其他解决方案,以消除依赖性。 一种这样的解决方案是Service Locator核心JEE模式:

android hilt 解耦 java中的解耦是什么意思_解耦_02

在此图中,客户端不直接引用目标,而是通过称为服务定位符的中间对象获取目标。 以下代码说明了这种模式,该代码执行JNDI查找:

publicclassServiceLocator{

    /** Singleton. */
    privatestaticServiceLocatorme;

    /** JNDI context to connect to. */
    privatefinalInitialContextcontext;

    /** Objects cache. */
    privateMapcache;

    /**
     * Gets an instance of the locator.
     *
     * @return Singleton
     * @throws NamingException
     */
    publicstaticServiceLocatorgetInstance()throwsNamingException{
        if(me==null){
            me=newServiceLocator();
        }
        returnme;
    }

    privateServiceLocator()throwsNamingException{
        context=newInitialContext();
    }

    /**
     * Get the object stored under the name in the JNDI tree. First look up in
     * the cache, then in the backing tree.
     *
     * @param name
     * @return Object stored
     * @throws NamingException
     */
    publicObjectlookup(Stringname)throwsNamingException{
        Objectobject=cache.get(name);
        if(object==null){
            object=context.lookup(name);
            cache.put(name,object);
        }
        returnobject;
    }
}


显然,此定位器非常简单,并采用了最简单的缓存策略。 但是,它有效。

自Java 1.3起,在JDK中就存在另一种形式的服务定位器(众所周知:只有真正的极客才知道),这是众所周知的(它是Service Provider) 。 此功能可以节省生命。 如果您将JAR(接口(API)和实现之一)完全分开,它可以让您将客户端代码与实现完全脱钩,并仅使用接口。 怎么做?

首先,您必须将代码干净地分开接口和实现(请参见上文)。 然后,对于每个接口,在META-INF / services下的实现JAR中创建一个新文件。 文件名应为接口的标准名称,文件内容应为所选实现的标准名称。 最后,在您的代码中,您应该只使用以下代码段:

java.util.ServiceLoader.load(MyFullyQualifiedInterfaceName.class);

就是这样,只要您注意将接口和实现JAR都放在类路径上即可。 不过要提一个警告:如果类路径上有多个实现,则无法确定选择。 现在,您可以通过这个简单而强大的技巧使同事惊讶。 如果您了解OSGI,那么您会发现它看起来很像OSGI服务层的雏形。 该解决方案的优点是您只需要JDK 1.3+。 缺点是您无法管理应用程序的生命周期,仅提供服务实现。