没有第三方框架的最简单的Java解耦

[…]耦合(或依赖性)是每个程序模块依赖于其他模块中每个模块的程度。
—维基百科
http://en.wikipedia.org/wiki/Coupling_(computer_science)

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

通过接口编程

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

publicclassA{
    privateCc=newB();
}

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

publicclassA{

    privateCc;

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

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

服务定位器模式

在此图中,客户端不直接引用目标,而是通过称为服务定位符的中间对象获取目标。 以下代码说明了此模式,该代码执行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中就存在另一种形式的服务定位器(尚不为人所知)(阅读:只有真正的极客才知道),它是服务提供者 。 此功能可以节省生命。 如果您将JAR(接口(API)之一和实现之一)完全分开,它可以让您将客户端代码与实现完全脱钩,并仅使用接口。 怎么做?

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

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

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

翻译自: https://blog.frankel.ch/simplest-java-decoupling-without-3rd-party-frameworks/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值