实现Singleton模式以在任何地方访问对象

目前,我有一个类,其构造函数采用用户名,密码和上下文。 我希望能够从任何地方访问这个对象,所以我想实现一个单例模式。

当前构造函数使用传入的凭据来validation通过该类的未来api调用。 如果我要实现单例模式,我首先想到的是让getInstace()方法获取用户名,密码等等,但每次我抓住一个实例时都必须传递该信息似乎是错误的。 因此我想在添加第一个实例时添加某种.authenticate(usr, pswrd)方法。

我的问题是,这是正确的方法吗? 如果没有,那么处理这个问题的好方法是什么? 下面是当前的代码:

构造函数:

 public Play(String username, String password, Context context) { api = getApi(username, password); Intent intent = new Intent(context, MyService.class); context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); //check if first run //if so, call api for info and store locally //if not, update as needed SharedPreferences pref = context.getSharedPreferences("pref", Context.MODE_PRIVATE); SharedPreferences.Editor editor = pref.edit(); if (pref.getBoolean("first_run", true)) { loadInitialData(context); } editor.putBoolean("first_run", false); editor.commit(); } 

Singleton模式限制类的实例化,并确保java虚拟机中只存在该类的一个实例。 单例类必须提供一个全局访问点来获取类的实例。 单例模式用于日志记录,驱动程序对象,缓存和线程池

此代码未经过测试,但应该让您了解如何在使用SharedPrefrencess使用singleton pattern

构造函数是私有的,因此只有getInstance()方法可以访问该实例,因此如果该类不存在或者先前实例化使用该实例,则将创建该类的实例

需要同步以确保多个线程在第一次尝试创建实例时

 import android.content.Context; import android.content.SharedPreferences; /** * Created by Pankaj Nimgade on 23-05-2016. */ public class Play { /** * volatile keyword ensures that multiple threads handle the uniqueInstance * variable correctly when it is being initialized to Singleton instance */ private volatile static Play play; private static final String XML_FILE = "play_xml_file.xml"; private static final String KEY_DATA = "SOME_DATA_KEY"; private static final String KEY_USERNAME = "SOME_USERNAME_KEY"; private static final String KEY_PASSWORD = "SOME_PASSWORD_KEY"; private static SharedPreferences sharedPreferences; private static SharedPreferences.Editor editor; private Play() { } public static Play getInstance(Context context) { if (play == null) { synchronized (Play.class) { if (play == null) { sharedPreferences = context.getSharedPreferences(XML_FILE, Context.MODE_PRIVATE); editor = sharedPreferences.edit(); play = new Play(); } } } return play; } public boolean saveSomeData(String someData) { editor.putString(KEY_DATA, someData); return editor.commit(); } public String readSomeData() { return sharedPreferences.getString(KEY_DATA, "default Value"); } public boolean saveUserNameData(String username) { editor.putString(KEY_USERNAME, username); return editor.commit(); } public String readUserNameData() { return sharedPreferences.getString(KEY_USERNAME, "default username Value"); } public boolean savePasswordData(String password) { editor.putString(KEY_PASSWORD, password); return editor.commit(); } public String readPasswordData() { return sharedPreferences.getString(KEY_PASSWORD, "default password value"); } } 

在上面的方法中我正在创建类lazy的实例,因为实例只会在需要时创建,尽管代码是线程安全的并且可以在所有Java版本上工作,如果你是的话你可能想要考虑不同的方法来实现它使用Java 5及以上版本。

https://sourcemaking.com/design_patterns/singleton/java/1

 public class Singleton { // Private constructor prevents instantiation from other classes private Singleton() {} /** * SingletonHolder is loaded on the first execution of Singleton.getInstance() * or the first access to SingletonHolder.INSTANCE, not before. */ private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } } 

与调用getInstance()的时刻相比,内部类不会被引用(因此不会被类加载器加载)。 因此,该解决方案是线程安全的,无需特殊的语言结构(即易失性或同步)。