1. 程式人生 > >Java設計模式--Builder模式

Java設計模式--Builder模式

Java設計模式–Builder模式

標籤(空格分隔): 設計模式

本文是遇到實際問題想辦法解決,並沒有詳細解釋理論,博主水平有限.

1.問題提出

問題的提出來源於實際程式碼中遇到的問題,下面講述問題.

公司做一個WebService服務,因為是二次開發的專案,所以json串都需要自己來定製,也就是要過濾很多屬性.

比如要定製下面的JSON串:

{
    "data": [{
        "order": 1,
        "path": "http://0b.jpg",
        "title": "聯想筆記本專場",
        "type": 1,
        "url
": "/mart/promotion/content/2.jhtml" }, { "order": 2, "path": "http://a.jpg", "title": "蘋果產品專場", "type": 2, "url": "#" }]
, "msg": "操作成功", "status": "0" }

之前的程式碼如下:
json解析器使用的是fastjson,框架用的是springMVC.

    @RequestMapping(value = "/figure", method = RequestMethod.GET
, produces = "application/json;charset=UTF-8") @ResponseBody public String figure(Long id) { public JSONObject figure(Long id) { AdPosition adPosition = adPositionService.find(id, true); Assert.notNull(adPosition); Set<Ad> ads = adPosition.getAds(); Assert.notEmpty
(ads); JSONObject res = new JSONObject(); res.put("status", ResultVo.OK.getStatus()); res.put("msg", ResultVo.OK.getMsg()); JSONArray data = new JSONArray(); for (Ad ad : ads) { JSONObject obj = new JSONObject(); obj.put("id", ad.getId()); obj.put("title", ad.getTitle()); obj.put("path", ad.getPath()); obj.put("order", ad.getOrder()); obj.put("url", ad.getUrl()); data.add(obj); } res.put("data", data); logger.debug(res.toString()); return res; }

這樣寫定製性強,但缺點也很明顯,程式碼量大,並且後面介面增多的話,程式碼重複率會增高.
隨著屬性欄位的增多,一個控制器會變得很臃腫.

改進的話,就是用構建器來構建

整個構建器結構為:主返回資訊類,該類的例項化通過內部靜態內部類來實踐,具體如下:

/**
 * 回覆資訊構造類
 * @author Niu Li
 * @date 2016/8/13
 */
public class ResultData {

    private String statu;
    private String msg;
    private JSONArray data;

    private ResultData(Builder builder) {
        this.statu = builder.statu;
        this.msg = builder.msg;
        this.data = builder.data;
    }

    /**
     * 構建器
     */
    public static class Builder{
        private String statu;
        private String msg;
        private JSONArray data;

        public Builder(String statu, String msg) {
            this.statu = statu;
            this.msg = msg;
        }
        public Builder(ResultVo resultVo) {
            this.statu = resultVo.getStatus();
            this.msg = resultVo.getMsg();
        }

        public Builder setData(JSONArray data) {
            this.data = data;
            return this;
        }
        /**
         * 定製json串,只轉換properties中指定name
         * @param clazz 要過濾的類
         * @param filters 要轉換的欄位
         * @param object 返回jsonArray或者jsonObject
         * @return
         */
        public Builder setData(Class<?> clazz, String[] filters, Object object){
            SimplePropertyPreFilter filter = new SimplePropertyPreFilter(clazz, filters);
            String result = JSON.toJSONString(object, filter);
            this.data = JSON.parseArray(result);
            return this;
        }

        public ResultData builder(){
            return new ResultData(this);
        }
    }

//省略get和set
}

這樣寫的好處不影響原來javaBean的形式,構建都是通過靜態內部類來實現,從而可以很方便的在其內部寫大量解析轉換程式碼,也可以在此基礎上實現流式風格程式設計.

更改後的程式碼如下:

    /**
     * 返回首頁輪播圖
     *
     * @param type 型別固定值 1
     */
    @RequestMapping(value = "/figure", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResultData figure(Long type) {
        AdPosition adPosition = adPositionService.find(type, true);
        Assert.notNull(adPosition);

        Set<Ad> ads = adPosition.getAds();
        Assert.notEmpty(ads);

        ResultData result = null;
        String[] filters = {"type", "title", "path", "order", "url"};
        result = new ResultData.Builder(ResultVo.OK)
                .setData(Ad.class, filters, ads)
                .builder();

        logger.debug(JSON.toJSONString(result));
        return result;
    }

相比之前的做法更加清晰,程式碼複用率提高不少.
即使增加其他欄位,只需要在構建器中增加相應的欄位,並且不影響其他的欄位輸出

關於構建器模式,有更為詳細的解釋,這些可以參考

http://blog.csdn.net/ydd326/article/details/6763517