Java設計模式--Builder模式
阿新 • • 發佈:2019-01-07
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