今天我在项目中看到了以下与JavaFX相关的代码:
issueComboBox.setConverter(new IntegerStringConverter());
yearComboBox.setConverter(new IntegerStringConverter());
并且想:我真的需要创建两个IntegerStringConverter实例吗?
IntegerStringConverter具有以下代码:
public class IntegerStringConverter extends StringConverter<Integer> {
@Override public Integer fromString(String value) {
if (value == null) {
return null;
}
value = value.trim();
if (value.length() < 1) {
return null;
}
return Integer.valueOf(value);
}
@Override public String toString(Integer value) {
if (value == null) {
return "";
}
return (Integer.toString(((Integer)value).intValue()));
}
}
所以我不需要两个实例,因为IntegerStringConverter中也没有状态 不在StringConverter中。 如果我可以重写该类,我会将其重写为单例,如下:
public final class IntegerStringConverter extends StringConverter<Integer> {
public static final IntegerStringConverter INSTANCE = new IntegerStringConverter();
private IntegerStringConverter() { }
@Override public Integer fromString(String value) {
if (value == null) {
return null;
}
value = value.trim();
if (value.length() < 1) {
return null;
}
return Integer.valueOf(value);
}
@Override public String toString(Integer value) {
if (value == null) {
return "";
}
return (Integer.toString(((Integer)value).intValue()));
}
}
因此,此类的用户无法创建多个实例:
issueComboBox.setConverter(IntegerStringConverter.INSTANCE);
yearComboBox.setConverter(IntegerStringConverter.INSTANCE);
它是来自javafx.util.converter包的类。 我认为它没有以我建议的方式实现,因为JavaFX开发人员 我想给我们扩展这个课程的可能性。
问题的关键是,实施课程几乎总是一个好主意( 这些不是纯辅助类,只有静态方法) 没有状态作为单例来阻止内存和性能的多个实例化 原因?
答案 0 :(得分:1)
我无法确切地说为什么在JavaFX中这样做是完全正确的。
可能有一种解释
Singleton不利于继承。您可以在将来扩展IntegerStringConvertor
以提供更具体的实施。
答案 1 :(得分:0)
如果您的IntegerStringConverter
类的任何方法都不会更改此类中成员的任何值,则可以将其作为单例传递。在你的情况下,它可以这样做,因为你甚至没有在你的班级成员
但是想象一下,这个类中有一个成员字段,由于方法调用会被修改,这不是一个好主意。这就像在这种情况下你必须是线程安全的。这就像问题,为什么不使用SimpleDateFormat
的单个实例进行多次调用。因为它不是线程安全的!请参阅:Why is Java's SimpleDateFormat not thread-safe?
所以,这将是一个坏主意:
public class Foo {
public static final Foo INSTANCE = new Foo();
private int value = 0;
public void changeIt() {
value++;
}
public int getValue() {
return value;
}
}
public class PrintThingy {
private static void print(Foo foo) {
foo.changeIt();
System.out.println(foo.getValue());
}
public static void main(String[] args) {
print(Foo.INSTANCE); // prints 1
print(Foo.INSTANCE); // prints 2 - huh!
}
}
所以,这真的取决于你在这个单例类中做了什么,以及你将单例实例传递给你的方法将会做什么!