实现Singleton模式以在任何地方访问对象 [英] Implementing the Singleton pattern for accessing an object anywhere

查看:117
本文介绍了实现Singleton模式以在任何地方访问对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Currently, I have a class whose constructor takes a username, password, and Context. I would like to be able to access this object from anywhere, so I was thinking of implementing a singleton pattern.

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

The current constructor uses the credentials passed in to authenticate future api calls through that class. If I were to implement the singleton pattern, my first thought would to be have the getInstace() method take a username, password, etc.., but it seems wrong to have to pass that info everytime i grab an instance. Because of this I was thinking of adding some sort of .authenticate(usr, pswrd) method to be called when grabbing the first instance.

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

My question is, is this the correct approach? If not, what would be a good way to handle this? Heres the current code:

构造函数:

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

This code is not tested but should give you an idea how you can use singleton pattern while using SharedPrefrencess.

构造函数是private,因此只有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");
    }
}

在上面的方法我正在创建实例class lazy,因为只有在需要时才会创建实例,尽管代码是线程安全的并且可以在所有Java版本上运行,如果您使用的是Java 5及更高版本,您可能需要考虑不同的方法来实现它。

in this above approach I am making instance creation of the class lazy, as the instance will only be created if demanded, although the code is thread safe and will work on all Java version you may want to consider different approach to implement this if you are using Java 5 and above.

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()的那一刻。因此,这个解决方案是线程安全的,不需要特殊的语言结构(即volatile或synchronized)。

The inner class is referenced no earlier (and therefore loaded no earlier by the class loader) than the moment that getInstance() is called. Thus, this solution is thread-safe without requiring special language constructs (i.e. volatile or synchronized).

这篇关于实现Singleton模式以在任何地方访问对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆