目前,我有一个类,其构造函数采用用户名,密码和上下文。我希望能够从任何地方访问这个对象,所以我想实现一个单例模式。
当前构造函数使用传入的凭据来验证通过该类的未来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();
}
答案 0 :(得分:1)
Singleton模式限制了类的实例化,并确保java虚拟机中只存在该类的一个实例。单例类必须提供一个全局访问点来获取类的实例。单例模式用于日志记录,驱动程序对象,缓存和线程池
此代码未经过测试,但应该让您了解在使用singleton pattern
时如何使用SharedPrefrencess
。
构造函数是私有的,因此只有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()的时刻相比,内部类不会被引用(因此不会由类加载器加载)。因此,该解决方案是线程安全的,无需特殊的语言结构(即易失性或同步)。