仅创建 1 个实例或单例
Creating only 1 instance or a Singleton
我用了一个叫'City'的class&整个游戏只有1个城市;如果只有1个或单例,创建一个实例是否有益。
class 本身将包含并非全部都是静态的方法,而且我读到单例本身仅由静态属性和方法组成并且可能是不好的做法,还是我弄错了?
我会使用单个实例并将其作为方法参数或作为构造函数依赖项提供在您需要使用它的地方。
这样您就可以在测试其他 类.
时轻松模拟它
单例是一种非常常见的模式。
在 java 中,它们是作为无法在外部创建的对象的私有实例生成的。
public class City {
private static City SINGLETON;
public static City get() {
// lazy construction, may be required to synchronize....
if( SINGLETON == null ) {
SINGLETON = new City();
}
return SINGLETON;
}
private City() {
... construct city here ....
}
// your City instance methods here (non-static)
....
}
如果您有一个依赖注入框架,您可以使用它来为您管理单例实例。
单例是一种非常常见的模式,可以帮助你在整个运行环境中只处理对象的一个实例。
所以不要担心区分静态和非静态方法...将它们全部设为非静态方法,因为 if 将仅通过 City.getInstance().method()
调用它们并且您确定 method() (以及任何其他方法)将仅在同一个实例上调用。
之前的答案是正确的,但是如果您在多线程环境中(作为 Web 应用程序),则必须以不同的方式实现单例,并且您需要确保只创建一个实例。
事实上,在前面的代码中,多个并发线程可能会创建一个新的 City 实例...稍后创建的线程将使用最后一个实例(因为它会覆盖静态字段中的第一个实例)。
有几种方法可以解决这个问题...最常见的是 synchronized
getInstance()
方法:
public static synchronized City getInstance() {
最高效的(高并发环境下)是使用惰性初始化:
public class City {
private static volatile City instance;
public static City getInstance() {
if( instance == null ) {
synchronized (City.class) {
if( instance == null ) {
instance = new City();
}
}
}
return instance;
}
private City() {
... construct city here ....
}
// your City instance methods here (non-static)
....
}
我在某处看到另一个基于 class 初始化的实现 "on demand"...
目前最好的单例机制是
public enum City {
INSTANCE;
}
然后你像这样引用实例
City.INSTANCE;
如果您所在的城市需要更多方法,您可以
public enum City {
INSTANCE;
private int xLoc;
public int getX() {
return xLoc;
}
}
用"creation guard"技术的单一对象是容易出错的。虽然他们有固定的 JVM,因此竞争条件不能确保创建两个实例(其中一个被垃圾收集),但这些示例中的 none 处理各种其他方式来复制您的实例。
例如,您可以序列化您的实例,然后反序列化它,这样您就有两个副本。
我用了一个叫'City'的class&整个游戏只有1个城市;如果只有1个或单例,创建一个实例是否有益。
class 本身将包含并非全部都是静态的方法,而且我读到单例本身仅由静态属性和方法组成并且可能是不好的做法,还是我弄错了?
我会使用单个实例并将其作为方法参数或作为构造函数依赖项提供在您需要使用它的地方。
这样您就可以在测试其他 类.
时轻松模拟它单例是一种非常常见的模式。
在 java 中,它们是作为无法在外部创建的对象的私有实例生成的。
public class City {
private static City SINGLETON;
public static City get() {
// lazy construction, may be required to synchronize....
if( SINGLETON == null ) {
SINGLETON = new City();
}
return SINGLETON;
}
private City() {
... construct city here ....
}
// your City instance methods here (non-static)
....
}
如果您有一个依赖注入框架,您可以使用它来为您管理单例实例。
单例是一种非常常见的模式,可以帮助你在整个运行环境中只处理对象的一个实例。
所以不要担心区分静态和非静态方法...将它们全部设为非静态方法,因为 if 将仅通过 City.getInstance().method()
调用它们并且您确定 method() (以及任何其他方法)将仅在同一个实例上调用。
之前的答案是正确的,但是如果您在多线程环境中(作为 Web 应用程序),则必须以不同的方式实现单例,并且您需要确保只创建一个实例。
事实上,在前面的代码中,多个并发线程可能会创建一个新的 City 实例...稍后创建的线程将使用最后一个实例(因为它会覆盖静态字段中的第一个实例)。
有几种方法可以解决这个问题...最常见的是 synchronized
getInstance()
方法:
public static synchronized City getInstance() {
最高效的(高并发环境下)是使用惰性初始化:
public class City {
private static volatile City instance;
public static City getInstance() {
if( instance == null ) {
synchronized (City.class) {
if( instance == null ) {
instance = new City();
}
}
}
return instance;
}
private City() {
... construct city here ....
}
// your City instance methods here (non-static)
....
}
我在某处看到另一个基于 class 初始化的实现 "on demand"...
目前最好的单例机制是
public enum City {
INSTANCE;
}
然后你像这样引用实例
City.INSTANCE;
如果您所在的城市需要更多方法,您可以
public enum City {
INSTANCE;
private int xLoc;
public int getX() {
return xLoc;
}
}
用"creation guard"技术的单一对象是容易出错的。虽然他们有固定的 JVM,因此竞争条件不能确保创建两个实例(其中一个被垃圾收集),但这些示例中的 none 处理各种其他方式来复制您的实例。
例如,您可以序列化您的实例,然后反序列化它,这样您就有两个副本。