我们可以通过创建私有getInstance方法和公共getter setter方法来创建Singleton类吗?

时间:2016-05-29 17:50:40

标签: java design-patterns singleton

Singleton类不仅仅意味着强制执行类的单个实例吗?如果是这种情况,与标准不同,我们不能在私有getInstance方法中使用getter-setter方法吗? 总之,下面是Classton类的一个例子吗?为什么/为什么不: -

public class MySingletonClass {
private MySingletonClass mySingletonClass;
private String name;
private MySingletonClass(){

}
private MySingletonClass getSingletonClassReference(){
    if(mySingletonClass==null){
        mySingletonClass = new MySingletonClass();
    }
    return mySingletonClass;
}

public static String getName() {
    return getSingletonClassReference().name;
}

public static setName(String name) {
    getSingletonClassReference().name = name;
}}

修改 由于上面的代码给出了编译时错误,这里是修改后的类代码。问题还是一样,我们不能有一个公共的getter-setter和私有的getInstance方法吗?为什么不呢?

public class MySingletonClass {
private static MySingletonClass mySingletonClass;
private String name;
private MySingletonClass(){

}
private static MySingletonClass getSingletonClassReference(){
    if(mySingletonClass==null){
        mySingletonClass = new MySingletonClass();
    }
    return mySingletonClass;
}

public static String getName() {
    return getSingletonClassReference().name;
}

public static void setName(String name) {
    getSingletonClassReference().name = name;
}}

5 个答案:

答案 0 :(得分:1)

根据已编辑的代码,您仍然无法保证MySingletonClass类的单实例创建。仍有可能两个实例将由两个并发调用创建。但是在这个例子中,我认为它不会影响你的方法中的其他过程!有道理。

鉴于你的代码:

考虑A和B想要调用setter方法, 先致电话。

getSingletonClassReference()将在setter内部调用,B同时调用setter。请求到达 if(mySingletonClass == null){ 它创造了一个对象。在那之前B到达条件null检查器并且将是真的,基本上它导致创建对象的两个实例。 如果我们假设B等待mySingletonClass = new MySingletonClass();和请求到达getSingletonClassReference()。name = name;然后B恢复执行,然后B覆盖名称,将忽略更改。

在您的示例中没有意义,但在实际应用程序中,它可能会在运行时导致错误并丢失数据。

最好在代码中应用同步,如下所示:

 public static Singleton getInstanceDC() 
    { 
       if (_instance == null) {
         // Single Checked 
         synchronized (Singleton.class) 
         { 
            if (_instance == null) 
            { // Double checked 
               _instance = new Singleton(); 
             } 
          }
        } 
     return _instance;
     }

了解详情:http://javarevisited.blogspot.com/2014/05/double-checked-locking-on-singleton-in-java.html#ixzz4A4QZAlJH

答案 1 :(得分:1)

如果问题是:Singleton是否可变?答案是肯定为什么不呢?但它必须是thread safe,而现在情况并非如此,您的代码中确实存在2个问题:

  1. 您不能阻止多个主题创建singleton,这意味着您的对象的多个实例可能会违反singleton的合同
  2. 您需要同时阻止读取和修改名称,否则您的主题将获得您名称的不一致值。
  3. 首先,这里是如何正确实现一个Singleton来做懒惰的创作,这显然是你想要的

    public class MySingletonClass {
        // The constructor must be private to prevent external instantiation
        private MySingletonClass(){};
        /** The public static method allowing to get the instance */
        public static MySingletonClass getInstance() {
            return MySingletonClassHolder.INSTANCE;
        }
        /**
         * The static inner class responsible for creating your instance only on demand,
         * because the static fields of a class are only initialized when the class
         * is explicitly called and a class initialization is synchronized such that only 
         * one thread can perform it, this rule is also applicable to inner static class
         * So here INSTANCE will be created only when MySingletonClassHolder.INSTANCE 
         * will be called
         */
        private static class MySingletonClassHolder {
            private static final MySingletonClass INSTANCE = new MySingletonClass();
        }
    }
    

    这解决了第1点,对于第2点,您可以在synchronizedgetName这两种方法的声明中添加关键字setName,或者只需添加关键字volatile变量name。最后一种方法是非阻塞这么快,这就是这种方法的样子:

    public class MySingletonClass {
    
        private volatile String name;
        ...
    

答案 2 :(得分:0)

单例意味着每个JVM只能有一个实例。这意味着在您的情况下,变量mySingletonClass必须是静态的(私有静态MySingletonClass mySingletonClass;`)以及get / setname。

关于规范,你的班级用户可能更难看到这是一个单身人士。

答案 3 :(得分:0)

您必须使方法getSingletonClassReference公开,但构造函数是私有的,因此您无法创建访问该方法的对象。因此,在这种情况下,您可以将方法设置为静态,以便其他类可以在不创建对象的情况下访问该方法。但是在你的getSingletonClassReferenc方法中,条件不对。在这里,您可以创建一个静态计数器来检查只创建了一个实例。

答案 4 :(得分:0)

是。那可以创造。 但是,您上面编写的代码需要修改。 getter,setter,getSingletonClassReference()和mySingletonClass字段应该是静态的。 但是,重要的是这不方便。