转载请注明出处,尊重作者劳动成果,谢谢!
个人觉得设计模式其实有以下两点好处,
1.可以在大型项目中增加可扩展性可维护性。
2.可以让你的编程更加美观和具有艺术性。
以上两点我一直觉得是作为一个标准程序员理应追求的境界,而不是光为了实现业务功能完成任务而写代码。
进入正题,以前编程的时候碰到一个问题,有一个水果类,有的页面是水果列表,服务端传回的数据是当前列表页(listview)需要用到的属性,有的是水果详情页(一堆layout),需要用到的又是水果其他不同的属性,有的是购物车里面的水果列表。这些数据都是从服务端返回的,我们肯定是需要解析的,而且一般我们Android的数据交互大多数都是用json作为和服务端的数据解析。
水果列表用到了,id,img,name,maketPrice(这个属性好扯淡)等属性,
水果详情页又用到了,id,name,img,productPlace(产地)等属性,
购物车列表页用到了,id,name,img,countNum(购买数量)等属性,
这个时候我们出于整体代码的维护性和扩展性尤其是为了单个类的可阅读性等考虑,很明显针对每一个不同的Json数据分别写一个解析类是很傻比的事情,思考之后就可以看得出来这些解析分别都有重复的解析字段,于是我就使用一个基类来保存id,name,img,三个属性,然后再分别新建不同的子类继承之,在子类里面再多出其他的解析代码来解析多余的属性。这样想想看应该是非常完善的。
但是这里有一个问题: 如果又多了一个页面,既需要用到maketPrice这个属性也需要用到productPlace属性,那是应该重新写一个子类继承父类然后再新增maketPrice和productPlace呢还是用其他的方法,或者大家再思考远一点,接下来的新业务还会有更多的扩展类需求,那都是不断的重写父类的解析法方法吗。这个方法显然不够具有艺术性以及导致大量代码的重复性。(用我们老大的话来说就是一点都不够专业)
最近在看老罗的源代码情景分析才了解到Android的UI层用了大量的装饰者模式(关于装饰者模式的具体概述,大家可以移步这个博客 http://blog.csdn.net/lenotang/article/details/2587265)。于是恍然大悟原来我碰到的问题可以用这个模式解决,于是生拉硬套了一番。代码如下:
首先是水果实体类 FruitItemBean:
public class FruitItemBean implements Parcelable{ private int productId;// 产品Id private String name;// 标题 private String imgs;// 图片地址 private double marketPrice;// 市场价 private String productPlace;//产地 private int countNum;//购买数量 }
然后是所有json解析类的解析接口
/** * 标题:FruitItem数据解析接口 * 作者: wxc * 时间: 2015/4/29 */ public interface Helper { public FruitItemBean getJsonData(JSONObject obj); }
装饰者类
/** * 标题:装饰者类 * 作者: wxc * 时间: 2015/4/29 */ public class DecorHelper implements Helper { private Helper mHelper; public DecorHelper(Helper helper) { mHelper = helper; } @Override public FruitItemBean getJsonData(JSONObject obj) { if (mHelper != null) { return mHelper.getJsonData(obj); } return mHelper.getJsonData(obj); } }
基础解析类
/** * 标题:基础解析类 * 作者: wxc * 时间: 2015/4/29 */ public class FruitBaseHelper implements Helper{ @Override public FruitItemBean getJsonData(JSONObject obj) { FruitItemBean item = new FruitItemBean(); //json解析建议大家自己手写一个工具类或者git上下载 item.setProductId(JsonUtil.getInt(obj, "id", 0)); item.setName(JsonUtil.getString(obj, "name", "")); item.setImgs(JsonUtil.getString(obj, "imgs", "")); return item; } }
水果列表页解析类
/** * 标题:水果列表所有数据 * 版权: 维度 * 创建时间: 2015-3-18 * 作者:wxc */ public class FruitItemHelper extends DecorHelper { public FruitItemHelper(Helper helper) { super(helper); } public FruitItemBean getJsonData(JSONObject obj) { FruitItemBean item = super.getJsonData(obj); item.setMarketPrice(JsonUtil.getDouble(obj, "marketPrice", 0)); return item; } //这个是解析列表的方法 public List<FruitItemBean> getFruitItemList(JSONObject obj) { List<FruitItemBean> list = CollectionUtil.newArrayList(); JSONObject data = JsonUtil.getJSONObject(obj, "data"); JSONArray array = JsonUtil.getJsonArray(data, "itemList"); if (array != null && array.length() > 0) { int length = array.length(); for (int i = 0; i < length; i++) { try { list.add(getJsonData(array.getJSONObject(i))); } catch (JSONException e) { e.printStackTrace(); } } } return list; } }
水果详情页解析类
/** * 标题:水果详情页解析 * 作者: wxc * 时间: 2015/4/29 */ public class FruitInfoHelper extends DecorHelper { public FruitInfoHelper(Helper helper) { super(helper); } public FruitItemBean getJsonData(JSONObject obj) { FruitItemBean item = super.getJsonData(obj); item.setProductPlace(JsonUtil.getString(obj, "productPlace", "")); return item; } }
水果购物车页解析数据类
/** * 标题:水果购物车页解析 * 作者: wxc * 时间: 2015/4/29 */ public class FruitShopCartHelper extends DecorHelper { public FruitShopCartHelper(Helper helper) { super(helper); } public FruitItemBean getJsonData(JSONObject obj) { FruitItemBean item = super.getJsonData(obj); item.setCountNum(JsonUtil.getString(obj, "countNum", "")); return item; } }
接下来是具体调用
//调用列表解析 List<FruitItemBean> list =new FruitItemHelper(new FruitBaseHelper()).getFruitItemList(json); //调用详情解析 FruitItemBean item = new FruitInfoHelper(new FruitBaseHelper()).getJsonData(json); //调用购物车解析 List<FruitItemBean> shoppingList = new FruitShopCartHelper(new FruitBaseHelper()) .getFruitItemList(json);
从这里可以看到,我刚才提出来的问题,如果有一个页面需要同时用到marketPrice和productPlace的时候只需要调用
FruitItemBean item = new FruitInfoHelper(new FruitItemHelper(new FruitBaseHelper())) .getJsonData(json);
有没有觉得很熟悉!!!!是不是曾经看到过这种调用!!!对!!!没有错!!!!除了androidUI组件,Java的IO流也大量用到了装饰者模式!比如 BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("..")));这样。是不是感觉!!!卧槽!!!!原来装饰者模式咱们都用过!!!好啦。。用过不代表会写。领悟才是王道。
到了这里已经把我自己的所有代码都重构完了,此文只给出了一种具体思路,由于本人一直都在创业团队做主程,没在大公司混过(真特么相进阿里啊!),对这种架构只能自己YY了,大家看看就好,我是属于无脑的生拉硬套。有更好的解决办法欢迎交流。