工厂设计模式
简单工厂模式
使用情景
在介绍前我先举一个例子就是,我们要缓存信息,这个时候我们通常使用SharePreference来进行缓存
package com.example.factormode.Utils;
import android.content.Context;
import android.content.SharedPreferences;
public class PreferenceUtils {
private volatile static PreferenceUtils mInstance;
private SharedPreferences mPreferences;
private SharedPreferences.Editor mEditor;
private PreferenceUtils(){
}
//这里用的是context,避免了内存泄漏
public void init(Context context){
mPreferences = context.getApplicationContext().getSharedPreferences("cache",Context.MODE_PRIVATE);
mEditor = mPreferences.edit();
}
public static PreferenceUtils getInstance(){
if(mInstance == null){
synchronized (PreferenceUtils.class){
if(mInstance == null){
mInstance = new PreferenceUtils();
}
}
}
return mInstance;
}
public PreferenceUtils saveString(String key,String value){
mEditor.putString(key,value);
return this;
}
public String getString(String key){
return mPreferences.getString(key,"");
}
public void commit(){
mEditor.commit();
}
}
使用就是先在BaseApplication中注册先
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
PreferenceUtils.getInstance().init(this);
}
}
在需要用到的地方使用
PreferenceUtils.getInstance().saveString("userName","hello").saveString("age","22").commit();
简单工厂介绍
好了,问题解决了,但是问题来了,后面需要用到新的缓存方式,存到硬盘中,存到缓存中,怎么办?写呗,这个时候发现就要改源码了,每个调用的地方都要改,不优雅。这个时候我们可以使用简单工厂设计模式
先弄一个IOHandle接口先
/**
* 数据存储的规范
*/
public interface IOHandle {
/**********save data start*******************/
void save(String key,String value);
void save(String key,double value);
void save(String key,int value);
void save(String key,long value);
void save(String key,boolean value);
void save(String key,Object value);
/**********save data end*******************/
/**********get data start*******************/
String getString(String key);
double getDouble(String key);
int getIng(String key);
long getLong(String key);
boolean getBoolean(String key);
Object getObject(String key);
/**********get data end*******************/
}
再弄一个Preference存储
public class PreferencesIOHandler implements IOHandle {
@Override
public void save(String key, String value) {
PreferenceUtils.getInstance().saveString(key,value);
}
...
//具体就不写了,懂意思就行了
...
@Override
public Object getObject(String key) {
return null;
}
}
再弄一个内存存储的方式
public class MermoryIOHandler implements IOHandle {
private static LruCache<String,Object> mCache = new LruCache<>(10*1024*1024);//运行内存1/8
@Override
public void save(String key, String value) {
mCache.put(key,value);
}
...
//具体就不写了,懂意思就行了
...
@Override
public Object getObject(String key) {
return null;
}
}
创建一个工厂
public class IOHandleFactor {
public enum IOType{
MEMORY,PREFERENCES
}
/**
* 通过IOHandle来获取所有的存储内存,我们是通过这种,方式来创建我们想要的存储方式
* 当需要加一个新的存储方式如写入数据库,我们需要将这个数据库继承IOHandle接口便可以了,不需要修改其地方,这个就是工程类的好 *处
* ,包括将一些新成时需要很多参数的地方,可以Builder+Factor结合来实现,从而减少使用者的麻烦
* @param ioType
* @return
*/
public static IOHandle createIOHandler(IOType ioType){
switch (ioType){
case MEMORY:
return new MermoryIOHandler();
case PREFERENCES:
return new PreferencesIOHandler();
default:
return null;
}
}
}
调用就是
//使用工厂设计模式来写
IOHandle ioHandle = IOHandleFactor.createIOHandler(IOHandleFactor.IOType.MEMORY);
ioHandle.save("userName","hello");
ioHandle.save("age","22");
很好很强大,以后添加新存储的方法只需要写一个继承IOHandle的类,再在IOHandleFactor中添加一个新的枚举就可以了
但是这里有一个不足之处,每次添加新的方法都要改动IOHandleFactor中的枚举和方法,那有没有更好的方法呢?
这个时候可以使用工厂设计模式。
工厂设计模式
工厂设计模式介绍
在上面我们都是用一个工厂来创建我们需要的工具(一个工厂生产多个工具),在工厂设计模式中就是直接创建工厂(也就是说一个工厂只生产一个工具)。
废话不多说直接上代码。
先弄一个创建工厂接口
/**
* 生成类的工厂接口
* 工厂方法模式,一个IOFactory -> 一个IOHandle
*/
public interface IOFactor {
IOHandle createIOHandler();
}
再弄一个Preference工厂
public class PreferencesIOFactory implements IOFactor {
@Override
public IOHandle createIOHandler() {
return new PreferencesIOHandler();
}
}
再弄一个Memory工厂
/**
* 运行在内存中的Factory
*/
public class MemoryIOFactory implements IOFactor {
@Override
public IOHandle createIOHandler() {
return new MermoryIOHandler();
}
}
使用
IOFactor ioFactor = new MemoryIOFactory();
com.example.factormode.simple3.IOHandle ioHandler = ioFactor.createIOHandler();
ioHandler.save("userName", "hello");
ioHandler.save("age", "22");
当我们常见一个新的储存方式的时候,例如我们需要存到硬盘中去,仅需要写一个handle再写一个工厂Factor就可以用,这样就不用我们来改动源码了
创建Handle
public class DiskIOHandler implements IOHandle {
....
}
创建工厂
public class DiskIOFactory implements IOFactor {
@Override
public IOHandle createIOHandler() {
return new DiskIOHandler();
}
}
抽象工厂设计模式
抽象工厂模式介绍
抽象工厂模式跟简单工厂设计模式比较相像,在简单工厂设计模式中,最主要的问题是switch很多对象,用到很多枚举,每每新增方法就需要改动过多。
抽象工厂就是想改变这种情况,他是利用反射来改变的。
这里修改的是简单工厂中的IOHandleFactor类,
public class IOHandleFactor {
/**
* 通过IOHandle来获取所有的存储内存,我们是通过这种,方式来创建我们想要的存储方式
* 当需要加一个新的存储方式如写入数据库,我们需要将这个数据库继承IOHandle接口便可以了,不需要修改其地方,这个就是工程类的好处
* ,包括将一些新成时需要很多参数的地方,可以Builder+Factor结合来实现,从而减少使用者的麻烦
*/
public static IOHandle createIOHandler(Class<? extends IOHandle> ioHandlerClass){
try {
return ioHandlerClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
//有问题就只返回PreferencesIOHandler
return new PreferencesIOHandler();
}
//这里新增方式不使用枚举,当需要新增方法的时候只需要新增一个新的方法。
/**
* 获取 内存 存储
* @return
*/
public static IOHandle getMemoryIOHandle(){
return createIOHandler(MermoryIOHandler.class);
}
/**
* 获取 SP 存储
* @return
*/
public static IOHandle getPrefencesIOHandle(){
return createIOHandler(PreferencesIOHandler.class);
}
/**
* 获取 磁盘 存储
* @return
*/
public static IOHandle getDiskIOHandle(){
return createIOHandler(DiskIOHandler.class);
}
/**
* 获取 默认 存储
* 默认的好处是创建的时候使用默认,当需要大范围更换,那就只需要我们更换Default里面的handle就行了
* @return
*/
public static IOHandle getDefaultIOHandle(){
return getPrefencesIOHandle();
}
}
这里我们使用**createIOHandler(Class<? extends IOHandle> ioHandlerClass)**来创建类,使用的是反射,每次通过新增一种方式只需要新增一个getXXXIOHandle()方法就可以了。尽可能减少源码的修改。
使用方式也和简单工厂类似
IOHandle ioHandle = IOHandleFactor.getDefaultIOHandle();
String userName = ioHandle.getString("userName");
String age = ioHandle.getString("age");
mTextView.setText(userName +" "+ age );