我們在實際開發中, 會有很多地方都需要緩存數據, 一些常用的需要緩存到內存中, 不常用的需要緩存到數據庫或者 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);
}
}
其實這樣寫是完全沒有問題的. 可是後面如果新增了別的存儲方式, 例如內存的, 數據庫的, 又要怎麼辦呢?
現在我們對它來改造一下.
- 先創建一個產品類接口. 裏面包含了所有存儲數據所需的基本功能
/**
* 定義數據存儲的基本方法
*/
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);
}
- 接着創建實體產品
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();
}
...
...
}
- 最後創建工廠類
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);
}
}
- 使用
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
即可.