【问题标题】:How to share data between separate classes in Java如何在 Java 中的不同类之间共享数据
【发布时间】:2010-12-12 00:37:04
【问题描述】:

在 Java 中的不同类之间共享数据的最佳方式是什么?我有一堆变量,不同的类以不同的方式在不同的文件中使用它们。 让我尝试说明我的问题的简化版本:

这是我之前的代码:

public class Top_Level_Class(){
    int x, y;

    // gets user input which changes x, y;
    public void main(){
       int p, q, r, s;
       // compute p, q, r, s
       doA(p,q,r);
       doB(q,r,s);
    }

    public void doA(int p, int q, int r){
       // do something that requires x,y and p, q, r
    }

    public void doB(int q, int r, int s){
       // does something else that requires x, y and q, r, s
    }
}

现在看起来像这样:

public class Top_Level_Class(){
    int x, y;
    SomeClass1a a = new SomeClass1a();
    SomeClass1a b = new SomeClass1b();
    // gets user input which changes x, y;
    public void main(){
       int p, q, r, s;
       // compute p, q, r, s
       a.doA(p,q,r);
       b.doB(q,r,s);
    }

public class SomeClass1a() {  // in its own separate file
    public void doA(int p, int q, int r){
       // do something that requires x,y and p, q, r
    }
}


public class SomeClass1b() {  // in its own separate file
    public void doB(int q, int r, int s){
       // does something else that requires x, y and q, r, s
    }
}

那么无论如何,我是否应该每次都传递 x 和 y(其中 x,y 是存储在辅助类 func 中的变量)?

 a.set(x,y);
 a.doA(p,q,r);

我的想法是有一个特殊的容器类来存放 x 和 y。顶级类将具有容器类的实例并使用 set 方法更改 x,y。

// in the top level class:
Container c = new Container(x,y);
a.setContainer(c);
b.setContainer(c);

我的辅助类也会有一个容器实例,它会指向与顶层相同的实例。这样他们就可以访问与顶层相同的 x,y。

我想知道我是否应该这样做

  • 使用容器类
  • 每次将 x,y 加载到子类中
  • ??一些更好的方法??

【问题讨论】:

  • 遗憾的是,这里的答案是“视情况而定”。对于这个问题,programmers.se 可能是更丰富的目标。
  • 如果内部类不是静态的,那么它也可以访问父类的成员......
  • 如果它在不同的文件中,它就不是一个内部类。如果它不扩展超类,它就不是子类。
  • 是的,子类对我来说是一个糟糕的选择。我会编辑这个。

标签: java oop class-design


【解决方案1】:

我想您的问题的答案是称为 Singleton 的设计模式。 它基本上允许您在系统中随时获取和利用相同(且唯一)的类实例。

这是它的实现(请原谅可能的语法错误,我没有编译它):

class Container{

  //eventually provides setters and getters
  public float x;
  public float y;
  //------------

  private static Container instance = null;
  private void Container(){

  }
  public static Container getInstance(){
    if(instance==null){
       instance = new Container();
      }
      return instance;
  }
}

然后,如果您在代码的其他地方导入了您可以编写的容器,例如

Container.getInstance().x = 3;
temp = Container.getInstance().x;

您将影响系统中唯一容器实例的属性

在许多情况下,最好使用依赖注入模式,因为它减少了不同组件之间的耦合。

【讨论】:

  • 非常有趣。它本身有一个静态变量。只是想知道,这件事是如何超出范围的?如果它是静态的,它不会一直存在吗?还是在我完成后将其设置为 null?
  • 对不起,但我想我没有理解你的问题 :( 无论如何,因为它的实例是静态的,一旦初始化,它将保持存在。你不必,也不能,将它设置为null。将其视为变量的共享存储库 :) 但是这里是对模式 en.wikipedia.org/wiki/Singleton_pattern 的解释
  • 嗯,如果我只需要实例化一次,那么单例将是有意义的。但是,我的顶级函数实际上是一个线程,将在整个程序执行过程中多次实例化/销毁。好吧,我想我每次都可以覆盖这些值。
  • 在系统执行过程中多次创建和销毁同一个线程是很奇怪的。您可能想要让它睡觉并在需要时唤醒它
  • 使用instance != null 而不是!instance,因为! 没有为此参数类型定义。
【解决方案2】:

我很难看出您的问题是什么——您为什么不想将 x 和 y 作为参数传递?

哦,好吧。假设您不这样做,我认为不需要新的容器类。这样做:

public class SubClass1a() {  // in its own separate file
    public void doA(Top_Level_Class caller, int p, int q, int r){
       // do something that requires x,y and p, q, r
       // **to get x use the expression term caller.getX() and caller.getY()**
    }
}

当然,您需要将公共 getter 方法 getX() 和 getY() 添加到 Top_Level_Class。

如果您不希望 SubClass1a 依赖于 Top_Level_Class,那么您可以创建一个接口来提供对变量的访问。

【讨论】:

  • 嗯,好吧。我将不得不更多地查看接口。我不想每次都传递 x,y 的主要原因是因为我在几个子类中有几个函数,每个函数都使用(x,y,z 等)并且每个传递 6-8 个变量似乎不正确时间我调用一个函数。子类曾经是依赖的,但我试图将它们从文件中取出,以便它们可以在不同的项目中使用。
  • @f20k 您对不想将 6-8 个参数传递给方法的直觉是正确的。这么长的参数列表通常暗示您应该考虑将这些参数捆绑到一个对象或 2 中。
  • @Dan,感谢您的建议。我想我会实现一个容器。这很有道理。我只是担心如果我以这种方式共享数据会是一种糟糕的编程习惯。
【解决方案3】:

块引用 我不想每次都传递 x,y 的主要原因是因为我在几个子类中有几个函数,每个函数都使用(x,y,z 等),并且每个传递 6-8 个变量似乎不正确时间我调用一个函数。子类曾经是依赖的,但我试图将它们从文件中取出,以便它们可以在不同的项目中使用。 块引用

如果是这种情况,那么您最好将变量抽象到容器类中。如果这些不再依赖的类的每个实例都将使用这些变量的一个大子集,那么将它们全部放在一个实例中是有意义的。逻辑上相关的变量应该在同一个地方找到。你的方法应该是这样的:

public class Top_Level_Class(){
Container container = new Container(x, y, p, q, r, s);
SubClass1a a = new SubClass1a(container);
SubClass1a b = new SubClass1b(container);
// gets user input which changes x, y using container's getters and setters
public void main(){
   // compute and set p, q, r, s
   a.doA();
   b.doB();
}

public class SubClass1a(Container c) {  // in its own separate file
    public void doA(c.getX, c.getY, c.getP, c.getQ, c.getR){
       // do something that requires x, y, p, q, and r
    }
}

public class SubClass1b(Container c) {  // in its own separate file

    public void doB(c.getX, c.getY, c.getQ, c.getR, c.getS){
       // does something else that requires x, y, q, r, and s
    }
}

public class Container(x, y, p, q, r, s) {
    //getters and setters for all variables
}

这可以防止您陷入变量传递意大利面条代码的情况,并且当您以后只想使用这些类中的一个或两个时,您的代码已经足够模块化,可以仅移植这些类和您的容器。

【讨论】:

  • 这个语法是错误的,而且看起来比原来的建议更复杂。
【解决方案4】:

这个问题有点疯狂——问题中的代码不会编译。

public class Main {
    public static void main(String... args) {
        MutableDataContainer m = new MutableDataContainer();
        ImmutableDataContainer i = computeImmutableData();
        new ADoer().doA(m, i);
        new BDoer().doB(m, i);
    }
    ...
}

class MutableDataContainer {
    private int x, y;
    ... // getters and setters below
}

class ImmutableDataContainer {
    private final int p, q, r, s;
    ... // getters below
}

您还需要定义ADoerBDoer

【讨论】:

  • 对不起,我在那里写的代码是为了帮助了解我想要做什么。它实际上不起作用。实际代码实际上相当复杂,有 100 多行。我基本上是在尝试在单独文件中的帮助类之间共享 top_level_class 中一些非常常用的变量。问题是哪种方法最好 - 高效和 oop-wise
猜你喜欢
  • 1970-01-01
  • 2018-04-01
  • 2018-03-25
  • 1970-01-01
  • 1970-01-01
  • 2018-05-25
  • 2011-06-03
  • 1970-01-01
  • 2021-10-16
相关资源
最近更新 更多