【问题标题】:Java how to extend a 3rd party application while keeping compatibilityJava 如何在保持兼容性的同时扩展 3rd 方应用程序
【发布时间】:2018-09-10 16:06:35
【问题描述】:

我正在开发一个基于开源项目的应用程序。我们付钱给开发人员,让他们根据他们的代码制作我们自己的应用程序,封闭源代码。我们确实希望与原始软件包保持兼容,安全和功能更新将与我们的应用程序合并。

当然,如果我大量修改原始代码,这里最大的问题是与新更新的合并。我在网上搜索了最佳解决方案,其中包括this one 之类的网站。所以我决定尽可能不修改原始代码。如果我想为现有功能添加功能,我扩展原始类,使应用程序指向我的扩展类(这是一个足够小的修改,不会成为问题),然后实现我的更改。

这里的问题是第 3 方类中的属性是我也想扩展的类型。在下面的示例中,class A 对属性myClass 进行了一些修改,我希望它继续这样做。但是扩展class Aclass B 包含一个类型扩展MyClass 本身的属性,这里是MyCustomClass。在class B 内部,我希望属性myCustomClassmyClass 的扩展,对myClass 所做的任何更改都应该可以在myCustomClass 中访问。

据我所知,将myClass 转换为myCustomClass 是不可能的,因为myClass 根本不是myCustomClass 类型。 那么在这里保持与class A 的兼容性并且不涉及仅从class A 复制所有代码的最佳解决方案是什么,因为如果class A 获得更新,这将产生完全相同的问题?

这里有一些示例代码可以更好地解释我的问题:

// Classes 'A' and 'MyClass' are 3rd party, I do not want to edit them
public class A {
    private MyClass myClass;

    A(){
        myClass = new MyClass();

        // Changes I want to keep doing
        doSomething();
    }

    public void doSomething(){
        // Do some calculations to myClass and modify it accordingly 
    }

    public MyClass getMyClass(){
        return myClass
    }
}


// Classes 'B' and 'MyCustomClass' are 1st party, I can do anything I want with them :)
public class B extends A{
    private MyCustomClass myCustomClass;        

    B(){
        super();

        myCustomClass = ?????????;


        // Extremely important message, this should keep working
        System.out.println(myCustomClass.verySpecialString);

        // Build further on made modifications, this should keep working too
        useModificationsByClassA();
    }

    public void useModificationsByClassA(){
        // Use result of class A's calculations in order to continue
    }
}


public class MyCustomClass extends MyClass{
    private String verySpecialString;

    MyCustomClass(){
        super();

        verySpecialString = "Hey!";
    }
}

【问题讨论】:

  • 我不相信你的愿望是可能的。在您扩展代码库的那一刻,维护更改成为您的责任。保持两者同步的唯一方法是将您对原始项目的更改作为开源提交。这样未来的版本也会有你的变化。这意味着原始代码提供者必须同意合并您的内容。
  • @duffymo,我的项目与原始代码相差很大。那是行不通的。如果这不可能,那么最接近的解决方案是什么?还是我唯一能做的就是复制class A的代码?
  • 复制代码?天哪,不。您可以将该库用作依赖项并编写自己的扩展。您承认并接受如果库进行更改,您将不得不升级以保持同步或留在旧版本上的风险。您应该将图书馆视为不可侵犯的 - 不要以任何方式更改它。扩展、包装、使用合成,但不要通过编辑源文件来扩展。
  • 是的,我知道我必须做一些工作才能保持更新。没关系。我在这里试图解决的一个具体问题是更改某些按钮的布局,最好不编辑原始代码。我将如何在扩展中做到这一点?
  • 摆动用户界面?好家伙。现在你遇到了一个问题,因为我怀疑作者是否对扩展点进行了很多思考,并使你可以轻松地做这样的事情。您可以编写自己的 JPanel,为其提供您想要的按钮,并使用侦听器对其进行配置,这些侦听器可以调用您希望它们拥有的库。但是该代码是您的全部。您只会使用他们的 API 将调用添加到按钮侦听器中以执行所需的任务。

标签: java open-source extend


【解决方案1】:

一般来说,在应用程序、库等中...有些组件是为扩展而设计的(因为虽然是为了),而其他一些组件实际上并不是为扩展而设计的。
但是修改现有组件通常不是扩展应用程序行为的方式。
因为现有的组件通常不是为了修改而设计的。他们的实际逻辑/处理可能会从一个版本强烈变化到另一个版本。这些可能会从源代码或其他任何内容中删除...... 因此,您将很难将原始源代码的更新合并到应用程序的修改实现的源代码中。

长话短说:应用程序可能允许扩展,但在这种情况下,它也提供扩展点,您不能以任何方式更改任何类。
如果你想扩展原始源代码的某些部分你必须知道实际的应用程序是否被设计为扩展,如果是,如何扩展
如果它不是为扩展而设计的,您应该接受应用程序更新可能不会集成(或难以集成)到修改后的应用程序中。

【讨论】:

  • 好的,但是如果它只是不被扩展,有没有办法可靠地添加更改?还是我只是运气不好?解决此类问题的常用方法是什么?
  • 可靠吗?永远不会有可能需要更改许多类/文件。您甚至可能需要更改测试类(如果有的话)。解决方案并不多:将应用程序作为内部分支在第一次可能很好,但以后也可能是冒险的赌注。
【解决方案2】:

考虑使用适配器或装饰器模式,并使用组合而不是继承。例如:

public class B {
    private final A a;        
    private final MyCustomClass myCustomClass;

    B(A a) {
        this.a = a;
        myCustomerClass = new MyCustomClass(a.getMyClass());
    }

   public void doSomething()  {
     a.doSomething();   // updates the state of a.myClass.
     myCustomerClass.doSomething();  // use the change of a.myClass to do more stuff         
   }
}

public class MyCustomClass {
   private final MyClass myClass;
   private String verySpecialString;

   public MyCustomClass(MyClass myClass) {
      this.myClass = myClass;
   }

   public void doSomething() {
      verySpecialString = "Hey!" + myClass.getSomeResult();
   }
}

【讨论】:

  • 谢谢。我之前考虑过这个解决方案并尝试过,但不是很喜欢它,因为它破坏了很多东西。但我想我没有太多选择,我会投入更多来尝试完成这项工作。如果这是我最终要做的事情,我会选择答案:)
  • @Andrew S OP 需要更改现有类以使更改生效。因此,实际上,组合将很长时间无法真正保护您,因为如果您通过另一个类(即合成器类)修改现有类,则必须更改对您更改的现有类的所有引用并注意修改.
猜你喜欢
  • 2012-01-15
  • 1970-01-01
  • 2015-05-19
  • 2014-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-14
  • 2011-04-04
相关资源
最近更新 更多