外观设计模式
定义
何为外观,就是对外提供一个统一的入口,一是可以隐藏系统内部的细节,二是可以降低使用者的复杂度,比如SpringMvc中的DispaterServlet,所有的Controller都是通过DispaterServlet统一暴露。
使用场景
降低使用者的复杂度,简化客户端的接入成本。
实践经验
有时候需要对外提供了一些开放能力给第三方ISV,比如设备管控、统一支付、对账单下载等能力,由于分属于不同的团队,所以对外提供的接口形式各异,初期还好,接口不多,ISV也能接受,但是后期接口多了ISV就开始抱怨接入成本太高,为了解决这一问题,在开放接口前面加了一层前端控制器GatewayController,其实就是后来开放平台的雏形,GatewayController对外统一暴露一个接口gateway.do,将对外接口的请求参数和响应参数统一在GatewayController做收敛,GatewayController往后端服务路由时也采用统一接口,改造前后对比如下图:
大概代码如下:
使用者:HttpClient.doPost("/gateway.do","{'method':'trade.create','sign':'wxxaaa','timestamp':'15311111111'},'bizContent':'业务参数'")GatewayController:
@RequestMapping("/gateway.do")
JSON gateway(HttpServletRequest req){ //1.组装开放请求OpenRequest openRequest = buildOpenRequest(req); OpenResponse openResponse = null; //2.请求路由if("trade.create".equals(openRequest.getMethod()){//proxy to trade service by dubboopenResponse = TradeFacade.execute(genericParam); } else if("iot.message.push".equals(openRequest.getMethod()){//proxy to iot service by httpclientopenResponse = HttpClient.doPost('http://iot.service/generic/execute'genericParam);} if(openResponse.isSuccess()){return {"code":"10000","bizContent":openResponse.getResult()};}else{return {"code":"20000","bizCode":openResponse.getCode()};}
}
总结
采用外观模式屏蔽了系统内部的一些细节,降低了使用者的接入成本,就拿GatewayController来说,ISV的鉴权,接口的验签等重复工作统一由它实现,ISV对接不同的接口只需要关心一套接口协议接口,由GatewayController这一层做了收敛。