我发现自己制作了许多用于GUI构建的类(因此它们必须符合JavaBean模式)。这为初始化创建了一些问题。我经常有一些时间密集的方法,必须在设置状态后执行。
一种方法是记录必须执行方法init()并希望人们阅读并尊重它,但这是笨拙的并且意味着GUIBuilder不能按预期使用,而是额外的代码必须添加。
我已经检查了Bloch" Effective Java"这些论坛,当然我问谷歌博士,但我还没有想出任何东西。公平地说,它有点像一套多余的搜索词。
以下简短示例(显然是无关紧要的)演示了我目前的做法。我有一个" isInitialised"每当调用setter时,都会变量并使实例无效。每当在计算变量(或任何其他复杂方法)上调用getter时,都会检查isInitialised变量,并在需要时调用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());
}
}
这种方法有很多问题。例如,它没有很好地扩展(其中一些确实是为了扩展)。另外,我在这里只展示了一个带有三个变量的简单案例;真正的课程还有很多。事情变得一团糟。
任何人都可以提出一种不同的方法或模式,可以帮助我保持代码更优雅和可读性,并且仍然允许在GUI构建器中按预期工作吗?
P.S。 这是可变的。
EDITED
我认为通过琐事,我隐藏了一点。
诀窍是我只想运行init()一次,并且只在设置完所有内容时才运行。如果我正在使用构建器模式,这将很容易,因为我将它放在build()方法中,但这是在GUI元素中,因此是在JavaBean模式中。
我上面的代码是"模式的简单版本"我在用。这个模式确实有效,但是我注意到有许多弱点,尤其是可扩展性(是一个单词吗?)以及随着变量数量的增加。这个简单的例子看起来不错,但真正的代码开始变得可怕。
我想这可能只是JavaBean模式的一个弱点,但我想在我在我的包中制作了另外十几个狡猾的类之前我会问。
答案 0 :(得分:1)
天真的方法:为什么不简单地在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);
}
}
答案 1 :(得分:0)
我认为我必须接受我想要实现的目标。以下是Bloch" Effective Java":
的引用不幸的是,JavaBeans模式有其严重的缺点 拥有。因为构造是跨多个调用分开的,所以是一个JavaBean 可能在其构造的中途处于不一致的状态。该 class没有选择仅通过强制执行一致性 检查构造函数参数的有效性。
虽然它并没有完全回答我的问题,但我认为围绕isInitialized变量的任何答案都会遇到Bloch描述的问题。