我发现自己制作了很多用于 GUI 构建的类(因此它们必须符合 JavaBean 模式)。这给我带来了一些关于初始化的问题。我经常有一些非常耗时的方法,必须在设置状态后执行。
一种方法是记录必须执行的方法 init() 并希望人们阅读并尊重它,但这很笨拙,并且意味着 GUIBuilder 不能按预期使用,而是必须添加额外的代码已添加。
我查过了 Bloch 的“Effective Java”、这些论坛,当然我还问过 Google 博士,但我还没有想出任何办法。公平地说,这组搜索词有点软弱无力。
下面的简短示例(显然是微不足道的)演示了我当前的方法。我有一个“isInitialized”变量,并且每当调用 setter 时都会使实例无效。每当对计算变量(或任何其他复杂方法)调用 getter 时,都会检查 isInitialized 变量,并在需要时调用 init() 方法。
public class BeanTest {
private int someValue; // Just some number
private float anotherValue; // Just another number
private double calculatedValue; // Calculated by some expensive process
private boolean isInitialised = false; // Is calculatedValue valid?
/**
* Default constructor made available for JavaBean pattern
*/
public BeanTest() {
someValue = 0;
anotherValue = 0;
}
//******* Getters and setters follow ************/
public int getSomeValue() {
return someValue;
}
public void setSomeValue(int someValue) {
if (someValue == this.someValue) {
return;
}
isInitialised = false; // Calculated value is now invalid
this.someValue = someValue;
}
public float getAnotherValue() {
return anotherValue;
}
public void setAnotherValue(float anotherValue) {
if (anotherValue == this.anotherValue) {
return;
}
isInitialised = false; // Calculated value is now invalid
this.anotherValue = anotherValue;
}
/**
* This is where the time expensive stuff is done.
*/
public void init() {
if (isInitialised) {
return;
}
/* In reality this is some very costly process that I don't want to run often,
* probably run in another thread */
calculatedValue = someValue * anotherValue;
isInitialised = true;
}
/**
* Only valid if initialised
*/
public double getCalculatedValue() {
init();
return calculatedValue;
}
/**
* Code for testing
*/
public static void main(String[] args) {
BeanTest myBean = new BeanTest();
myBean.setSomeValue(3);
myBean.setAnotherValue(2);
System.out.println("Calculated value: " + myBean.getCalculatedValue());
}
}
这种方法有多个问题。例如,它不能很好地扩展(其中一些确实是为了扩展)。另外,我在这里仅展示一个包含三个变量的简单案例;真正的类(class)还有更多。事情变得一团糟。
任何人都可以建议一种不同的方法或模式来帮助我保持代码更加优雅和可读,并且仍然允许事情在 GUI 构建器中按预期工作吗?
附注 这意味着是可变的。
已编辑
我认为通过轻描淡写我有点隐藏了要点。
诀窍是我只想运行 init() 一次,并且仅在一切设置完毕后运行。如果我使用构建器模式,这会很容易,因为我会将其放在 build() 方法中,但这是在 GUI 元素中,因此在 JavaBean 模式中也是如此。
我上面的代码是我正在使用的“模式”的简单版本。该模式确实有效,但正如我所指出的,存在许多弱点,特别是可扩展性(这是一个词吗?)以及随着变量数量的增长。这个简单的示例看起来不错,但真正的代码开始看起来很可怕。
我想这可能只是 JavaBean 模式的一个弱点,但我想在我的包中制作另外十几个狡猾的类之前我应该先问一下。
最佳答案
天真的方法:为什么不在 setter 中简单地调用 init() 呢?
更奇特一点:使用 PropertyChangeSupport目的。使用示例:
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
public class TestBean implements PropertyChangeListener{
private int someValue;
private PropertyChangeSupport changeSupport;
public TestBean() {
changeSupport = new PropertyChangeSupport(this);
changeSupport.addPropertyChangeListener(this);
}
private void init() {
//do something time consuming, maybe even on a different thread, using Futures?
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
init();
}
public int getSomeValue() {
return someValue;
}
public void setSomeValue(int someValue) {
int oldValue = this.someValue;
this.someValue = someValue;
changeSupport.firePropertyChange("someValue", oldValue, someValue);
}
}
关于java - 初始化 JavaBean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26396850/