几乎总是把没有州的班级写成单身人士?

时间:2014-01-30 14:50:08

标签: java singleton

今天我在项目中看到了以下与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开发人员 我想给我们扩展这个课程的可能性。

问题的关键是,实施课程几乎总是一个好主意( 这些不是纯辅助类,只有静态方法) 没有状态作为单例来阻止内存和性能的多个实例化 原因?

2 个答案:

答案 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!
    }
}

所以,这真的取决于你在这个单例类中做了什么,以及你将单例实例传递给你的方法将会做什么!