Android 中使用工廠模式來管理數據緩存及存儲

我們在實際開發中, 會有很多地方都需要緩存數據, 一些常用的需要緩存到內存中, 不常用的需要緩存到數據庫或者 SD 卡中.

這些需要緩存的數據對我們來說, 內部的結構差異並不是很大, 都是存取數據. 如果說爲每一種存儲都單獨寫一個工具類來供我們調用, 也是可以的. 但是入口不統一, 後期維護起來, 可能會造成一部分的麻煩, 很有可能會到處去修改. 這個例子就是使用工廠模式讓我們優雅的管理數據的緩存和存儲, 會更方便後期的維護.

開始正文.
平時我們使用 SharedPreferences 存儲的時候, 是不是就是直接創建一個工具類呢? 像下面這樣

public class PreferencesUtils {

    private static volatile PreferencesUtils mInstance;
    private SharedPreferences mSharedPreferences;
    private SharedPreferences.Editor mEditor;

    private PreferencesUtils() {
    }

    public void init(Context context) {
        mSharedPreferences = context.getApplicationContext().getSharedPreferences(
                CacheKey.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
        mEditor = mSharedPreferences.edit();
    }

    public static PreferencesUtils getInstance() {
        if (mInstance == null) {
            synchronized (PreferencesUtils.class) {
                if (mInstance == null) {
                    mInstance = new PreferencesUtils();
                }
            }
        }
        return mInstance;
    }

    public PreferencesUtils putString(String key, String value) {
        mEditor.putString(key, value);
        return this;
    }

    public String getString(String key) {
        return mSharedPreferences.getString(key, "");
    }
    ...
    ...
    ...
    public void commit() {
        mEditor.commit();
    }
}

然後在我們自己的 BaseApplication 中初始化這個工具類

public class BaseApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        PreferencesUtils.getInstance().init(this);
    }
}

其實這樣寫是完全沒有問題的. 可是後面如果新增了別的存儲方式, 例如內存的, 數據庫的, 又要怎麼辦呢?
現在我們對它來改造一下.

  1. 先創建一個產品類接口. 裏面包含了所有存儲數據所需的基本功能
/**
 * 定義數據存儲的基本方法
 */
public interface ICache {
    ICache putObjectCache(String cacheKey, Object value);
    ICache putBooleanCache(String cacheKey, boolean value);
    ICache putStringCache(String cacheKey, String value);
    ICache putLongCache(String cacheKey, long value);
    ICache putDoubleCache(String cacheKey, double value);
    ICache putIntCache(String cacheKey, int value);
    void putCommit();
    //--------------------------------------------------------------------
    Object getObjectCache(String cacheKey);
    boolean getBooleanCache(String cacheKey, boolean defaultValue);
    String getStringCache(String cacheKey);
    long getLongCache(String cacheKey, long defaultValue);
    double getDoubleCache(String cacheKey, double defaultValue);
    int getIntCache(String cacheKey, int defaultValue);
}
  1. 接着創建實體產品 PreferencesCache, MemoryCache, DiskCache 分別實現抽象產品
public class PreferencesCache implements ICache {

    private SharedPreferences mSharedPreferences;
    private SharedPreferences.Editor mEditor;

    private PreferencesCache(Context context){
        mSharedPreferences = context.getApplicationContext().getSharedPreferences(
                CacheKey.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
        mEditor = mSharedPreferences.edit();
    }

    @Override
    public ICache putStringCache(String cacheKey, String value) {
        //PreferencesUtils.getInstance().putString(cacheKey, value);
        mEditor.putString(cacheKey, value);
        return this;
    }

    @Override
    public String getStringCache(String cacheKey) {
        //return PreferencesUtils.getInstance().getString(cacheKey);
        return mSharedPreferences.getString(cacheKey, "");
    }

    @Override
    public void putCommit() {
        //PreferencesUtils.getInstance().commit();
        mEditor.commit();
    }

    ...
    ...
}
  1. 最後創建工廠類
public class CacheFactory {

    private static volatile CacheFactory mInstance;
    private ICache mMemoryCache, mDiskCache, mPreCache;
    private Context mContext;

    private CacheFactory() {
    }

    public static CacheFactory getInstance() {
        if (mInstance == null) {
            synchronized (CacheFactory.class) {
                if (mInstance == null) {
                    mInstance = new CacheFactory();
                }
            }
        }
        return mInstance;
    }

    public void init(Context context){
        this.mContext = context;
    }

    private ICache createCache(Class<? extends ICache> clazz) {
        ICache cache = null;
        try {
            if(clazz.getCanonicalName().equals(PreferencesCache.class.getCanonicalName())){
                Constructor constructor = clazz.getDeclaredConstructor(Context.class);
                cache = (ICache) constructor.newInstance(mContext);

            }else {
                cache = clazz.newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cache;
    }

    public ICache getMemoryCache() {
        if (mMemoryCache == null) {
            return createCache(MemoryCache.class);
        }
        return mMemoryCache;
    }

    public ICache getPreferencesCache() {
        if (mPreCache == null) {
            return createCache(PreferencesCache.class);
        }
        return mPreCache;
    }

    public ICache getDiskCache() {
        if (mDiskCache == null) {
            return createCache(DiskCache.class);
        }
        return mDiskCache;
    }

    public ICache getDefaultCache() {
        if (mPreCache == null) {
            return createCache(PreferencesCache.class);
        }
        return mPreCache;
    }
}

當然, 也可以不使用這種方式, 在每個方法內, 也可以不調用 createCache, 而是使用直接創建對象的方式. 這個就看個人怎麼選擇了.
當然, 別忘記了在 Application 中初始化我們的工廠

public class BaseApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        //PreferencesUtils.getInstance().init(this);
        CacheFactory.getInstance().init(this);
    }
}
  1. 使用
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tv = findViewById(R.id.tv);
        String userName = CacheFactory.getInstance().getPreferencesCache().getStringCache(CacheKey.KEY_USER_NAME);
        if (TextUtils.isEmpty(userName)) {
            CacheFactory.getInstance().getPreferencesCache()
                    .putStringCache(CacheKey.KEY_USER_NAME, "張三")
                    .putCommit();
            //CacheFactory.getInstance().getMemoryCache().putStringCache(CacheKey.KEY_USER_NAME, "李四");
            //CacheFactory.getInstance().getDiskCache().putStringCache(CacheKey.KEY_USER_NAME, "李四");
        } else {
            tv.setText(userName);
        }
    }
}

這樣就改造完成了, 後面有修改, 比如我們不需要用到 SharedPreferences 來存儲了, 那麼直接新建一個實體產品類, 然後在工廠裏替換一下 PreferencesCache 即可.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章