java8 函数式编程_Java 8函数式编程:延迟实例化

java8 函数式编程

单例通常会延迟实例化自己,有时,如果对象足够重,则可以延迟实例化类字段。

通常,在走惰性路线时,getter方法(或accessor )必须具有一段代码,该代码块在返回对象之前检查是否已实例化该对象(如果不是,则需要实例化)。 一旦实例化了对象,该检查就没有意义。 它只会减慢已(通常)使用同步或锁定进行阻塞的方法的速度。 让我们看一下删除该代码的方法,对吗?

免责声明

我没有想到这个。 我是从Venkat Subramaniam的Java函数编程中获得的。 我强烈推荐这本书和作者。 Venkat所阅读的所有内容都做得很好,而且易于学习。

它是如何工作的?

基本思想是:

  1. 将延迟实例化的字段替换为所需类型的供应商。
  2. 供应商实例化该对象(但尚未返回它)
  3. 然后将字段设置为新的Supplier,该供应商仅返回实例化的对象
  4. 返回实例

因此,让我们看看实际情况。 我们将有一个名为Holder的类,该类要延迟实例化Heavy类型的对象。 此代码直接从Venkat的书中编译而成:

public class Holder
{
   private Supplier heavy = () -> createAndCacheHeavy();
 
   public Heavy getHeavy()
   {
      return heavy.get();
   }
 
   private synchronized Heavy createAndCacheHeavy()
   {
      class HeavyFactory implements Supplier
      {
         private final Heavy heavyInstance = new Heavy();
 
         public Heavy get()
         {
            return heavyInstance;
         }
      }
     
      if(!HeavyFactory.class.isInstance(heavy))
      {
         heavy = new HeavyFactory();
      }
 
      return heavy.get();
   }
}

现在,此代码可以正常工作,但是我发现createAndCacheHeavy的实现不必要地令人困惑。 第一次看到此代码时,我花了很长时间才弄清楚它在做什么。

因此,让我们对其进行一些修改,对吧? 我们将使它看起来像是按照我之前列出的步骤进行操作。

private Heavy createAndCacheHeavy()
{
   Heavy instance = new Heavy();
   heavy = () -> instance;
   return instance;
}

那不是更好吗? 我认为,这比以前更简单,更干净。 而且仍然有效! 好吧,这里有一个小警告:为了使代码具有线程安全性,您需要同步getInstance()方法而不是createAndCacheHeavy方法。 与Venkat的代码相比,这种更改会使代码的速度稍慢一些,因为一旦HeavyFactory到位,他的代码就不会使用同步。 但是它仍然比每次都需要同步和有条件检查的旧方法要快。

因此,这是一些有用的代码,但是您是否想在每次懒惰地实例化某些东西时都键入该代码? 我不这么认为。 因此,让我们创建一个可重用的类,使我们的生活更加轻松。

但是首先,只是为了向您展示它变得更容易使用,让我向您展示它的使用情况。

Supplier<Heavy> heavy = LazilyInstantiate.using(() -> new Heavy());

而已! 让我们更仔细地看一下它,并深入研究它,然后再进行研究。

该行的声明位与以前相同; 一家名为Heavy的重型供应商。 但是随后我们调用了LazilyInstantiate的静态方法,该方法原来是返回工厂实现Supplier的LazilyInstantiate对象的静态工厂方法。 传递给该方法的参数是在那里的“重型供应商”,因此用户可以为实例化器提供正确的代码以实例化对象。

那么,您是否对它的工作方式感到好奇? 好,这是LazilyInstantiate的代码:

public class LazilyInstantiate implements Supplier
{
   public static  LazilyInstantiate using(Supplier supplier)
   {
      return new LazilyInstantiate<>(supplier);
   }
     
   public synchronized T get()
   {
      return current.get();
   }
     
   private LazilyInstantiate(Supplier supplier)
   {
      this.supplier = supplier;
      this.current = () -> swapper();
   }
     
   private final Supplier supplier;
   private Supplier current;
     
   private T swapper()
   {
      T obj = supplier.get();
      current = () -> obj;
      return obj;
   }
}

您可能会发现我的方法的顺序与通常的方法有所不同。 我更喜欢先拥有公共的东西,然后拥有私有的和受保护的包裹,然后拥有私有的东西。 在这些块中,我执行静态字段,然后构造函数,然后是静态方法,然后是普通字段,然后是普通方法。 通常,这似乎按照用户阅读我的代码的最重要程度至最不重要的顺序对事物进行了排序。

您可以随意将代码复制到任何地方,也可以在github上查看我的Functional-java库 ,该具有此类的完整文档版本(func.java.lazy.LazilyInstantiate)和许多其他有用的函数类。

翻译自: https://www.javacodegeeks.com/2015/01/java-8-functional-programming-lazy-instantiation.html

java8 函数式编程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值