【问题标题】:Extract a lambda from a Factory refactoring (with an IDE)?从工厂重构中提取 lambda(使用 IDE)?
【发布时间】:2013-12-09 09:01:13
【问题描述】:

我有一个工厂,它在我的项目中的太多地方实现,大约 40 个。我希望我的代码与现代技术兼容,并决定使用接口来确保它可以与 Java 8 兼容(lambdas 可以'不实现抽象类)。有没有一种安全的方法,即组合重构来做到这一点?

我有:

 class Factory{
     String name;
     protected Object globalContext;

     public abstract Session newSession();
 }

我需要:

 interface NewSessionFunction{
     Session create(Factory enclosingFactory);
 }

 class Factory{
     protected String name;
     protected Object globalContext;

     protected final NewSessionFunction newSession;

     public Factory(NewSessionFunction newSession){
         this.newSession = newSession;
     }

     public Session newSession(){
         return newSession.create(this);
     }

     public Object getData() {return globalContext;}
 }

目标是:

 new Factory((self) -> new MySession(self))

代替:

 new Factory(){
     public newSession(){
         return new MySession();
     }
 }

我还没有找到提取 lambda 的方法,但好奇是否有可用的方法?

更新

我的问题是如何轻松重构现有代码,因为我已经有 40 个抽象类的实现。如果使用现有工具无法轻松完成此重构功能,我认为可能会在 IDE 中引入此重构功能。许多 Java 7 代码库工厂理论上可以与 lambda 一起使用,但 Java 8 不允许使用 lambda 实例化它们。所以一个可能的出路是将抽象方法提取到 lambda 中。

【问题讨论】:

  • 为什么要把工厂包装成工厂?为什么你不只有一个接口工厂和一个方法 createSession()?我认为应该这样做。
  • 这是一个创建会话(lambdas)的工厂,它可以完成一些工作。我需要在多个线程中运行这个 lambda,所以我复制了它。
  • 你当前的工厂有额外的字段和方法。谁调用了这些额外的方法?
  • 这些字段是一些在会话内部使用的全局信息。此信息可用于安排或调用其他会话。这很复杂,我试图通过要求“提取 lamda 重构”来尽可能地简化它。
  • 最后一部分self到底是什么意思?在同一行中创建的Factory 实例?

标签: java lambda refactoring java-8


【解决方案1】:

更新

经过几次 ping-pong cmets,这个问题的目标是找到一个可能的 IDE 功能,以帮助在 Java 8 中将抽象类重构为 lambda 表达式。据我所知,eclipse Luna 不支持此功能此时。

更新前回答

玩弄你的想法:

(我已经假设)但请确保 NewSessionFunction 被标记为功能接口:

@FunctionalInterface
interface NewSessionFunction{
  Session create(Factory f);
}

以下是可能的

interface Session {
}
static class MySession implements Session {
  public MySession(Object globalContext) {
  }
}
Session s = new Factory((Factory f) -> 
  {return new MySession(f.getData());}).newSession();

但是,self 的想法并不是我在任何参考资料中实际看到的。 提供参考(如果您知道的话)。在同一行中,您可能想尝试以下导致编译错误的方法:

new Factory((Factory f) -> {
  return NewSessionFunction.this.create(f);}).newSession();

我不确定你的重构在多大程度上是可行的,但将“共享”数据重构为可以在Session 的不同工厂之间共享的对象持有者引用可能是一个好主意,这也使得lambda 表达式的使用更加直接和自然。

更新后回答

想一想如何以最小的变化维持这一点,以下内容对您有何帮助?

static abstract class LegacyFactory {
    private Object globalContext;
    protected Object getData() {
        return globalContext;
    }
    public abstract Session newSession();
}
@FunctionalInterface
static interface NewFactory {
    Session newSession();
}

static class FactoryWrapper {
    public static NewFactory wrap(final LegacyFactory f) {
        return () -> {
            return f.newSession();
        };
    }
}

【讨论】:

  • 是的,这是可能的。我的问题是如何轻松重构现有代码,因为我已经有 40 个抽象类的实现......我认为如果使用现有工具无法轻松完成此功能,他们可能会在 IDE 中引入此功能。一些现有工厂的问题是理论上它们可以与 lambdas 一起使用,但 Java 8 不允许使用 lamdas 实例化它们。所以一个可能的出路是将抽象方法提取到 lambda 中。
  • 现在我明白了。我建议将您的问题重新命名为“使用 IDE 从抽象类中提取 lambda 表达式?”
  • 有兴趣知道您对更新后答案的看法。
  • 好吧,在某些情况下,创建包装器可能会有所帮助。我的案例 40 类并没有那么多手动编辑,我不想维护两个版本,所以经过一个小时的艰苦工作,它完成了:link。我仍然对如何实现自动化感兴趣。 :-)
【解决方案2】:

Netbeans (Dev 201311200002) 不支持此功能。不确定 Eclipse。我不确定您是否想要一个可以执行大量专用重构的 IDE,而您会花更多的时间学习而不是使用。你只需要两件事:

  • 编译器。更改 Factory 的签名后,它将显示所有需要修复的地方。 (是的静态类型语言!)
  • 复制和粘贴(或查找和替换)以减少打字。

顺便说一句,对新工厂的调用可以简化为:

new Factory(Session::new);

【讨论】:

  • 我确实经常使用它们,有时重构可以创造奇迹,尤其是在大型项目中。 IDE 对我的支持是 Java 的优势之一。
猜你喜欢
  • 1970-01-01
  • 2014-03-29
  • 1970-01-01
  • 2016-01-07
  • 1970-01-01
  • 2016-10-06
  • 2021-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多