2

I was reading about singletons the other day and thought to implement them in a project of mine, but I didn't like the way it seemed to flow logically, so I created what I'd call a controller class to manage the state of the singleton object. I want to make sure that the logic checks out though, and that I'm not inadvertently spawning off additional instances.

//Controller for SaveSystem, allows the class to be created once for the 
//duration of the application at the global level (believe this is called a 
//singleton pattern)

public class SaveSystemContr {
  private static SaveSystem saveSystemInstance;
  public SaveSystem GetSaveSystemData() {
    return saveSystemInstance;
  }

  public void SetSaveSystem(SaveSystem _saveSystem) {
    if(saveSystemInstance!=null) {
        saveSystemInstance=_saveSystem;
    }
  }

  public static SaveSystem getSaveSystemInstance(final FirebaseAuth _auth, final LoadProjFragment _LFP) {
    if(saveSystemInstance==null) {
        saveSystemInstance = new SaveSystem(_auth, _LFP);
    }

    return saveSystemInstance;
  }

  public SaveSystemContr() {} //THE WAY IS SHUT!
}

Edit* I do not view this as a duplicate of the question referenced, as that was a typical/standard implementation of a singleton, and this uses a different model altogether by utilizing a controller to manage the state of the singleton.

4

2 回答 2

1

我想确保逻辑检查出来,并且我不会无意中产生额外的实例。

看起来您可以根据需要创建任意数量的实例:

SaveSystemContr controller = new SaveSystemContr();

// Create instance 1
controller.SetSaveSystem(new SaveSystem(auth, lfp));

// Create instance 2
controller.SetSaveSystem(new SaveSystem(auth, lfp));

// ...

如果您只想要 1 个实例,为什么还要使用 setter 方法?

一个非常基本的单例将如下所示:

public final class SaveSystemSingleton {
  // This class should only be accessed statically. Don't allow instance creation
  private SaveSystemSingelton() {}

  private static SaveSystem saveSystem;

  // Encapsulate creation logic. Passing in params is misleading because
  // all subsequent calls will do nothing with the params.
  public static SaveSystem get() {
    // If accessing from multiple threads do Double Check Locking instead!
    if (saveSystem == null) {
      saveSystem = new SaveSystem(new FirebaseAuth(), new LoadProjFragment());
    }
    return saveSystem;
  }
}

如果确实需要传入params,定义一个单独的静态setter方法,如果多次调用或者get()没有先调用setter就抛出异常。

此外,您应该检查依赖注入(例如Dagger2),这使得创建对象实例和确定它们的范围变得清晰和容易。

于 2018-02-03T04:59:50.477 回答
1

将构造函数设为私有并移除 getter 和 setter:

    //Allows the OBJECT (not class) to be created once only    
    public class SaveSystem {

      private static SaveSystem saveSystemInstance;

      //make constructor private 
      private SaveSystem(final FirebaseAuth _auth, final LoadProjFragment _LFP) {
        //todo complete constructor
      }

      public static SaveSystem getSaveSystemInstance(final FirebaseAuth _auth, final LoadProjFragment _LFP) {
        if(saveSystemInstance==null) {
            saveSystemInstance = new SaveSystem(_auth, _LFP);
        }   
        return saveSystemInstance;
      } 
    }

如您所见,它可以在SaveSystem没有控制器的情况下应用。

于 2018-02-03T05:11:50.860 回答