首页 > 解决方案 > Java应用程序在初始化时返回超类

问题描述

现在我们正在编写一些核心应用程序,所有其他应用程序都将依赖这些应用程序。不用多说,让我用一些代码解释逻辑,

我们曾经有一个 1000 多行长的 java 文件,每个应用程序都将它作为类在里面,所以当发生变化时,每个应用程序都必须编辑其中的 java 文件,或者简单地修复一个并复制到所有. 这很难实现,也很难维护。然后我们最终将其创建为一个单独的应用程序,该应用程序被划分为更小的部分,易于维护,而且核心可能是对其他应用程序的依赖,因此我们在一个地方修复,所有其他代码应用程序也已修复。

一段时间以来,我一直在为此考虑一些很棒的结构,想为此使用构建器模式,如下所示

TheCore theCore = new TheCore().Builder()
.setSomething("params")
.setSomethingElse(true)
.build();

现在问题出现了。像这样,我初始化了对象,但现在我public只能访问该对象类。这个应用程序实际上将有许多小类,它们具有public我不希望它们成为每次都可以调用的静态方法的功能。TheCore相反,我希望只有在类被初始化时才调用这些方法;

// doSomething() will be from another class
theCore.doSomething()

我产生了一些想法

someOtherClass.doSomething(theCore)

将主对象作为参数注入,但仍someOtherClass需要初始化,甚至需要一个静态方法,这让我感觉不舒服,而且是正确的方法。

实际上,我不在乎初始化TheCore是否会给我带来一个超级对象,该对象包含所有其他类在初始化并准备好在我初始化后访问TheCore。我只希望在这个结构中拥有一个可维护的单独应用程序和可用的方法,前提是仅TheCore初始化这种情况下的主要对象。

什么是实现它的正确方法?我看到Java不允许扩展多个类,即使这样做,我不确定这是正确的方式......

谢谢。

标签: java

解决方案


在花费大量时间思考之后,我最终认为

// doSomething() will be from another class
theCore.doSomething()

不适合,因为许多 java 类可能具有相同的方法名称。所以...

// doSomething() will be from another class
theCore.someOtherClass.doSomething()

将是一个更好的方法。

为了更容易理解,我将不得不遵循一个复杂的路径来解释它,首先从包类开始。

认为我有一个名为的包Tools和一个类SomeFancyTool

main
└─java
  └─com
    └─<domainName>
      ├─Tools
      | └─SomeFancyTool.java
      └─TheCore.java           

现在这SomeFancyTool.java必须有一个默认访问级别,实际上是包级别访问,因为我不希望直接访问这些类;

SomeFancyTool.java

package com.<domainName>.Tools

class SomeFancyTool{
   
   public String someStringMethod(){
      return "Some string!";
   }

   public int someIntMethod(){
      return 123;
   }

   public boolean someBooleanMethod(){
      return true;
   }

}

所以现在我们有了这个SomeFancyTool.java类,但TheCore.java不能访问它,因为它Tools只能通过它的包来访问。在这一点上,我想到了一个将在同一个包中的 Initializer 类,初始化这些私有类并在调用时用一个函数返回它们。所以初始化器类看起来像这样;

工具初始化器.java

package com.<domainName>.Tools

public class ToolsInitializer{
   private SomeFancyTool someFancyTool = new SomeFancyTool();
   
   public SomeFancyTool getSomeFancyTool(){
      return someFancyTool;
   }

}

由于ToolsInitializer.java可以初始化Tools包内的所有功能私有类,也可以将它们作为对象返回到包范围之外,因此我们仍然无法使用这些方法,因为我们无法使用这些方法,import com.<domainName>.SomeFancyTool因为TheCore.java它是包范围内可访问的。我认为在这里我们可以从 java 的实现中受益interface。一个不是单独起作用的类,所以即使它被访问也没有问题,因为它的方法只不过是声明。

在这一点上,我将重命名SomeFancyTool.java它将SomeFancyToolImplementation.java实现interface并调用SomeFancyTool.java接口本身。

SomeFancyTool.java(现在作为接口)

package com.<domainName>.Tools

public interface SomeFancyTool{

   public String someStringMethod();

   public int someIntMethod();

   public boolean someBooleanMethod();

}

并让我们先重命名SomeFancyTool.java并实现interface

SomeFancyToolImplementation.java(重命名)

package com.<domainName>.Tools

class SomeFancyToolImplementation implements SomeFancyTool{

   @override
   public String someStringMethod(){
      return "Some string!";
   }

   @override
   public int someIntMethod(){
      return 123;
   }

   @override
   public boolean someBooleanMethod(){
      return true;
   }

}

现在我们的结构在最后的编辑中变成了这样;

main
└─java
  └─com
    └─<domainName>
      ├─Tools
      | ├─SomeFancyTool.java
      | ├─SomeFancyToolImplementation.java
      | └─ToolsInitializer.java
      └─TheCore.java           

最后,我们可以使用我们的TheCore.java类调用所有初始化类及其方法,以将所有这些私有类作为对象接收。这将允许外部应用程序首先调用和初始化TheCore以便能够访问其他方法。

TheCore.java

public class TheCore{
   private SomeFancyToolImplementation someFancyTool;

   public static class Builder{
      private SomeFancyToolImplementation someFancyTool;

      public Builder(){
         ToolsInitializer toolsInitializer = new ToolsInitializer();
         someFancyTool = toolsInitializer.getSomeFancyTool();
      }
  
      public Builder setSomeValues(){
         //some values that is needed.
         return this;
      }

      public Builder setSomeMoreValues(){
         //some values that is needed.
         return this;
      }

      public TheCore build(){
         TheCore theCore = new TheCore();
         theCore.someFancyTool = someFancyTool;
         return theCore;
      }

   }

}

全部完成,可以使用了。现在,它所依赖的功能包类及其方法是否TheCore已初始化,无法通过 out 访问TheCore。从 3rd 方应用程序中简单地使用这个库就是:

第 3 方应用程序

TheCore theCore = new TheCore.Builder()
                      .setSomeValues("Some Values")
                      .setMoreSomeValues("Some More Values")
                      .build();
theCore.someFancyTool.someStringMethod();

注意:请注意,aToolsInitializer.java仍然可以访问,并且可以在不首先调用的情况下使用 get 私有方法,但是如果不满足某些先决条件,TheCore我们总是可以在getSomeFancyTool()方法内部设置一个检查器来出错。throw

我仍然不知道这是要使用的功能结构模式还是我的一些艰难的想法。并且不知道是否已经存在一些我还看不到的模式,但这是我最终得到的解决方案。


推荐阅读