源代码
GitHub源代码
1.本文目标
因为公司接下来的业务要在其他城市扩张,所以我们的App也要相应的跟上业务。所以想写一套扩展性比较强的方案,核心思想就是,以后不管扩张多少个城市,走一套代码,然后一个城市对应一个配置文件,业务变更就添加或者修改配置文件而不用去修改业务代码。
2.使用步骤
1.创建城市配置的model(ConfigModel)
2.创建城市配置的model对应的配置文件(放在assets目录下,一个城市对应一个配置文件)
3.创建城市配置管理类(CityConfigManager),这个类的作用就是把配置文件中的数据给转换成相应的对象(就是ConfigModel对象)
4.根据客户所属不同的城市去切换不同的配置信息,从而实现一套代码对应多个城市
3.具体Demo示例如下
步骤1.创建城市配置的model,所有信息都在这里
public class ConfigModel {
private String mCity;
private float mManagementFeeRatio;//管理费比例
private boolean mIsShowEarnestMoney;//是否显示定金
public ConfigModel(){}
public String getCity() {
return mCity;
}
public void setCity(String city) {
this.mCity = city;
}
public float getManagementFeeRatio() {
return mManagementFeeRatio;
}
public void setManagementFeeRatio(float managementFeeRatio) {
this.mManagementFeeRatio = managementFeeRatio;
}
public boolean isShowEarnestMoney() {
return mIsShowEarnestMoney;
}
public void setIsShowEarnestMoney(boolean isShowEarnestMoney) {
this.mIsShowEarnestMoney = isShowEarnestMoney;
}
@Override
public String toString() {
return "ConfigModel{" +
"mCity='" + mCity + '\'' +
", mManagementFeeRatio=" + mManagementFeeRatio +
", mIsShowEarnestMoney=" + mIsShowEarnestMoney +
'}';
}
}
步骤2.在assets资源文件下创建config文件夹,然后在里面放置每个城市的配置文件,一个城市对应一个配置文件,下面的截图是北京的配置文件,然后这个文件中的第一行是ConfigModel的全路径包名,下面的这些字段是要和ConfigModel中的字段一一对应起来,因为下面的第3步要通过反射去找这个字段

步骤3.创建城市配置管理类,目的在于把配置文件中的所有信息读取出来,然后通过反射创建ConfigModel对象,并把配置文件中的字段信息给赋值上去,这样一来就可以随意调用这个ConfigModel类中的信息了
public class CityConfigManager {
private CityConfigManager() {
}
public static CityConfigManager getInstance() {
return Holder.INSTANCE;
}
private static class Holder {
private static final CityConfigManager INSTANCE = new CityConfigManager();
}
/**
* 根据不同的城市得到相应的ConfigModel对象
*/
public ConfigModel getConfigModel(String city) {
ConfigModel config = null;
try {
switch (city) {
case "北京":
config = getCityConfigByFile(MyApp.getContext(), "beijing.txt");
break;
case "上海":
config = getCityConfigByFile(MyApp.getContext(), "shanghai.txt");
break;
case "三体":
break;
case "成都":
break;
case "昆山":
break;
case "无锡":
break;
default:
break;
}
} catch (Exception e) {
e.printStackTrace();
}
return config;
}
/**
* 从资源配置文件中读取数据并转化成ConfigModel对象
*/
private ConfigModel getCityConfigByFile(Context context, String city) throws Exception {
InputStream is = context.getAssets().open("config/" + city);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
//读取配置文件完整类名
String className = bufferedReader.readLine();
className = fixString(className);
//通过类的全包名去创建无参对象
Class clazz = Class.forName(className);
Constructor constructor = clazz.getConstructor(null);
Object o = constructor.newInstance(null);
String line;
while ((line = bufferedReader.readLine()) != null) {
String[] data = line.split("=");
Field field = clazz.getDeclaredField(data[0]);
field.setAccessible(true);
if (field.getType() == byte.class) {
field.set(o, Byte.parseByte(data[1]));
}
else if (field.getType() == short.class) {
field.set(o, Short.parseShort(data[1]));
}
else if (field.getType() == int.class) {
field.set(o, Integer.parseInt(data[1]));
}
else if (field.getType() == long.class) {
field.set(o, Long.parseLong(data[1]));
}
else if (field.getType() == float.class) {
field.set(o, Float.parseFloat(data[1]));
}
else if (field.getType() == double.class) {
field.set(o, Double.parseDouble(data[1]));
}
else if (field.getType() == boolean.class) {
field.set(o, Boolean.parseBoolean(data[1]));
}
else {
field.set(o, data[1]);
}
}
ConfigModel config = (ConfigModel) o;
return config;
}
/**
* BufferedReader的readLine()方法有bug,首行第一个字符会是一个空字符,所以修复一下
*/
private String fixString(String str) {
char s = str.trim().charAt(0);
//65279是空字符
if (s == 65279) {
if (str.length() > 1) {
str = str.substring(1);
}
}
return str;
}
}
步骤4. 因为客户经理管理了很多客户,有的客户是北京有的是上海然后马上就有成都昆山无锡等城市,可以在客户模块和订单模块去赋值该客户是属于哪个城市,从而实现动态切换配置
public void test1(View view) {
ConfigModel model = mConfigManager.getConfigModel("北京");
mTextView.setText(model.toString());
System.out.println(model.getManagementFeeRatio());//得到北京的管理费的比例
System.out.println(model.isShowEarnestMoney());//得到北京地区是否要显示定金
}
public void test2(View view) {
ConfigModel model = mConfigManager.getConfigModel("上海");
mTextView.setText(model.toString());
System.out.println(model.getManagementFeeRatio());//得到上海的管理费的比例
System.out.println(model.isShowEarnestMoney());//得到上海地区是否要显示定金
}
4.总结
目前这个方案是基于现有的项目,这是第一步,把所有涉及到城市相关的代码都通过配置文件的方式去进行一个管理,不管有多少个城市,以后只需要修改或者添加配置文件而不用去修改业务代码,这也符合开闭原则.
网友评论