前言:
前沿技術一直在迭代,有一種東西是不會更新的,那就是設計模式的思想。 可以來學習學習設計模式的思維,巧妙設計!
外觀模式就是整合多個對象到一個對象,對外暴露一個,常用接口簡化!
適配模式,簡單的說是接口轉化,將不符合,不對外的接口轉化符合,對外而已。
[TOC]
1.官方話語
概述
設計模式(Design Pattern)是一套被反復使用、多數(shù)人知曉的、經過分類的、代碼設計經驗的總結。
六大原則:
單一職責原則 (Single ResponsiBility Principle) 概括:應該有且僅有一個原因引起類的變更
里氏替換原則(liskov Substitution Principle ) 概括:基類出現(xiàn)的地方,子類一定可以出現(xiàn)
依賴倒轉原則(Depndece Inversion Principle) 概括:針對接口編程,依賴于抽象而不是具體
接口隔離原則(Interface Segregation Principle) 概括:使用多個隔離的接口,比使用單個接口好 (細分接口,降低耦合)
迪米特法則 (Demeter Principle) 概括:實體應當盡量少的與其他類發(fā)生互相作用,使得系統(tǒng)功能模塊相對獨立
開閉原則(Open Close Principle) 概括: 對擴展開放,對修改關閉
合成復用原則 (Composite Reuse Principle) 概括:盡量使用合成/聚合的方式,少用繼承
個人話語
概述
設計模式在代碼層級中,是讓你在某種業(yè)務場景剛開始設計時,能讓未來的相關需求擴展極為方便的一個思想。
簡單的說,在一開始設計好,擴展是很方便的,設計模式就是這個功勞者。
對于我們本來就懶的開發(fā)人員來說,這是求之不得的。
六大原則
而對于六大原則,簡單過一下就行,不用刻意理解,如果你會了面向對象和設計模式的使用,自然就遵循了。
今日主題
適配模式:將一個類的接口變換成客戶端所期待的另一種接口,從而使本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。
外觀模式:要求一個子系統(tǒng)的外部與其內部的通信必須通過一個統(tǒng)一的對象進行,外觀模式提供一個高層次的接口,使得子系統(tǒng)更易于使用
場景:
這次我引入了一個我實際的案例,具體看碼云 adapter ——》practice,巧妙的使用了適配和外觀
,其實也算是一種簡單的策略
概述:
代碼如下
'適配和外觀全部'代碼
package top.huey.designpattern.adapter.demo;
/**
* @author huey
* @Description : 面向客戶端實體類
* @Date Created in 2018/8/26 15:30
*/
public interface MyToClient {
public void consume(String str);
}
package top.huey.designpattern.adapter.demo;
/**
* @author huey
* @Description : 面向客戶端實體類
* @Date Created in 2018/8/26 15:30
*/
public interface MyToClient {
public void consume(String str);
}
package top.huey.designpattern.adapter.demo;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
/**
* @author huey
* @Description : 外觀模式
* @Date Created in 2018/8/26 16:28
*/
@Data
@RequiredArgsConstructor
public class MyFacade {
@NonNull
private MyToClient myToClient;
@NonNull
private MyToClient2 myToClient2;
/**
*對外
*/
public void faceApi(String api){
myToClient.consume(api+"對外");
myToClient2.consume2(api+"對外");
}
}
package top.huey.designpattern.adapter.demo;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
/**
* @author huey
* @Description : 適配對象
* @Date Created in 2018/8/26 15:32
*/
@Data
@RequiredArgsConstructor
public class MyAdapter1 implements MyToClient {
@NonNull
private MyAdaptee myAdaptee;
@Override
public void consume(String str) {
myAdaptee.say(str);
}
}
package top.huey.designpattern.adapter.demo;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
/**
* @author huey
* @Description : 適配對象
* @Date Created in 2018/8/26 15:32
*/
@Data
@RequiredArgsConstructor
public class MyAdapter2 implements MyToClient2 {
@NonNull
private MyAdaptee myAdaptee;
@Override
public void consume2(String str) {
myAdaptee.say(str);
}
}
package top.huey.designpattern.adapter.demo;
/**
* @author huey
* @Description : 被適配者 不面向用戶(程序員)
* @Date Created in 2018/8/26 16:19
*/
public class MyAdaptee {
public void say(String str){
System.out.println("我是被適配者"+ str);
}
}
package top.huey.designpattern.adapter.demo;
import org.junit.Before;
import org.junit.Test;
/**
* ┏┓ ┏┓
* ┏┛┻━━━┛┻┓
* ┃ ┃
* ┃ ━ ┃
* ┃ ┳┛ ┗┳ ┃
* ┃ ┃
* ┃ ┻ ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ 神獸保佑
* ┃ ┃ 代碼無BUG!
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*
* @author huey
* @Description : 適配器用于 不同接口之間的轉化,被適配者與客戶端隔離,
* @Date Created in 2018/8/26 11:35
*/
public class AdapterTest {
MyAdaptee myAdaptee = null;
@Before
public void before() {
//被適配對象
myAdaptee = new MyAdaptee();
}
@Test
public void test1() {
/**
*創(chuàng)建適配器對象
*/
MyToClient myToClient = new MyAdapter1(myAdaptee);
MyToClient2 myToClient2 = new MyAdapter2(myAdaptee);
/**
*面向客戶端
*/
myToClient.consume("hello world");
myToClient2.consume2("hello world");
/**
*外觀模式
*/
MyFacade myFacade = new MyFacade(myToClient, myToClient2);
myFacade.faceApi("hello");
}
}
'業(yè)務中三方對接使用適配,外觀,策略等思想'部分代碼
package top.huey.designpattern.adapter.practice.emi.test;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import top.huey.designpattern.adapter.practice.business.AdminInfo;
import top.huey.designpattern.adapter.practice.emi.adapter.EMIAdapter;
import top.huey.designpattern.adapter.practice.emi.api.EMIAPI;
import top.huey.designpattern.adapter.practice.emi.config.EMIConfigTest;
import top.huey.designpattern.adapter.practice.emi.enums.AccountEnum;
import top.huey.designpattern.adapter.practice.emi.enums.EMIAPIEnum;
import java.util.Map;
public class TestMi {
public static Logger logger = LoggerFactory.getLogger(TestMi.class);
public static void main(String[] args) throws Exception {
logger.info("--------------------start---------------------------");
// logger.info(TestMi.class.toString() + GetResult_Test(1));
//
// AdminInfo adminInfo = new AdminInfo();
// adminInfo.setEmiWorkNumber("044814");
// String resutByAPI = GetResult_Test(EMIAPI.CALL_RECORD_URL, adminInfo, null);
//
//// String resutByAPI = GetResult_Test(EMIAPI.CALL_INSERT, adminInfo, null);
// EMIResult emiResult = JSONObject.parseObject(resutByAPI, EMIResult.class);
// logger.info("--------------------end---------------------------" + emiResult.getResp().getCallRecordUrl().getUrl());
// String url = "[https://ks3-cn-beijing.ksyun.com/yimi-record-1-year/1003_0001355f_913124753505_liuerlei_17621043172_2_20180723_172226_172341_75_7388929.mp3?Expires=1532428885&response-content-type=application%2Foctet-stream&response-content-disposition=attachment%3B%20filename%3D1003_0001355f_913124753505_liuerlei_17621043172_2_20180723_172226_172341_75_7388929.mp3&KSSAccessKeyId=AKLT0ChC2dqZRK6viMM8BwGZLQ&Signature=oIUKa9eqeztXH2Rs6nGtbVoWeYA%3D](https://ks3-cn-beijing.ksyun.com/yimi-record-1-year/1003_0001355f_913124753505_liuerlei_17621043172_2_20180723_172226_172341_75_7388929.mp3?Expires=1532428885&response-content-type=application%2Foctet-stream&response-content-disposition=attachment%3B%20filename%3D1003_0001355f_913124753505_liuerlei_17621043172_2_20180723_172226_172341_75_7388929.mp3&KSSAccessKeyId=AKLT0ChC2dqZRK6viMM8BwGZLQ&Signature=oIUKa9eqeztXH2Rs6nGtbVoWeYA%3D)";
//
// String path = "E:\\11111.mp3";
// //path 自定義, 名稱 callId TODO
// EMIAdapter.copyToServer(url, path);
}
/**
* EMIAdapter.doJsonPost(EMIConfigTest.SUP_PATH + AccountEnum.EMI_SUP.getAccId() + EMIAPIEnum.HUEY_TEST.getPart(), jsonData.toString(), AccountEnum.EMI_SUP.getAccId(), AccountEnum.EMI_SUP.getToken())
*/
/**
* @param
* @return
* @description 寫個大接口,方便測試和調用 欠優(yōu)化
* @author: huey V1.0 2017/10/30 21:44
*/
public static String GetResult_Test(int num, AdminInfo adminInfo, Map map) {
JSONObject jsonData = new JSONObject();
JSONObject internalJSON = new JSONObject();
switch (num) {
case 1://查詢子賬戶 ok
internalJSON.put("appId", EMIConfigTest.APP_ID);
internalJSON.put("subAccountSid", AccountEnum.EMI_SUB.getAccId());
jsonData.put("subAccount", internalJSON);
return EMIAdapter.doJsonPost(EMIConfigTest.SUP_PATH + AccountEnum.EMI_SUP.getAccId() + EMIAPIEnum.HUEY_TEST.getPart(), jsonData.toString(), AccountEnum.EMI_SUP.getAccId(), AccountEnum.EMI_SUP.getToken());
case 2://查詢主賬戶 ok
return EMIAdapter.doJsonPost(EMIConfigTest.SUP_PATH + AccountEnum.EMI_SUP.getAccId() + EMIAPIEnum.HUEY_TEST2.getPart(), null, AccountEnum.EMI_SUP.getAccId(), AccountEnum.EMI_SUP.getToken());
case 3: //創(chuàng)建坐席1000 ok
internalJSON.put("appId", EMIConfigTest.APP_ID);
internalJSON.put("workNumber", "gh1356");//工號
internalJSON.put("phone", "13124753505");
jsonData.put("createUser", internalJSON);
return EMIAdapter.doJsonPost(EMIConfigTest.SUB_PATH + AccountEnum.EMI_SUB.getAccId() + EMIAPIEnum.ENTERPRISES_CREATE_USER.getPart(), jsonData.toString(), AccountEnum.EMI_SUB.getAccId(), AccountEnum.EMI_SUB.getToken());
case 4: //更新號碼
internalJSON.put("appId", EMIConfigTest.APP_ID);
// internalJSON.put("workNumber", "1001");
internalJSON.put("number", "1001");
internalJSON.put("phone", "15531001282");
jsonData.put("updateUserPhone", internalJSON);
return EMIAdapter.doJsonPost(EMIConfigTest.SUB_PATH + AccountEnum.EMI_SUB.getAccId() + EMIAPIEnum.ENTERPRISES_UPDATE_PHONE.getPart(), jsonData.toString(), AccountEnum.EMI_SUB.getAccId(), AccountEnum.EMI_SUB.getToken());
case 5: //簽入
internalJSON.put("appId", EMIConfigTest.APP_ID);
internalJSON.put("workNumber", "gh1356");
internalJSON.put("deviceNumber", "");
jsonData.put("signIn", internalJSON);
return EMIAdapter.doJsonPost(EMIConfigTest.SUB_PATH + AccountEnum.EMI_SUB.getAccId() + EMIAPIEnum.SIGN_IN.getPart(), jsonData.toString(), AccountEnum.EMI_SUB.getAccId(), AccountEnum.EMI_SUB.getToken());
case 6://雙向
internalJSON.put("appId", "957ccdb87fdc364b71c784a144ba0681");
internalJSON.put("from", "15531001283");
internalJSON.put("to", "15531001283");//13161189722
internalJSON.put("displayMode", "0");
internalJSON.put("userData", "123456");
jsonData.put("callBack", internalJSON);
return EMIAdapter.doJsonPost(EMIConfigTest.SUB_PATH + AccountEnum.EMI_SUB.getAccId() + EMIAPIEnum.CALL_BACK.getPart(), jsonData.toString(), AccountEnum.EMI_SUB.getAccId(), AccountEnum.EMI_SUB.getToken());
case EMIAPI.CALL_OUT: //呼出 ok
internalJSON.put("appId", EMIConfigTest.APP_ID);
internalJSON.put("workNumber", "admin");//工號
internalJSON.put("to", "13124753505");
// internalJSON.put("userData", "");
jsonData.put("callOut", internalJSON);//api0040001355f1527154715219vQlP3
return EMIAdapter.doJsonPost(EMIConfigTest.SUB_PATH + AccountEnum.EMI_SUB.getAccId() + EMIAPIEnum.CALL_OUT.getPart(), jsonData.toString(), AccountEnum.EMI_SUB.getAccId(), AccountEnum.EMI_SUB.getToken());
case EMIAPI.ADD_[ENTERPRISE://addEnterpise](enterprise://addEnterpise/)
//esp": { "respCode": 0, "addEnterprise": { "provinceId": "4", "enterpriseId": "78657", "enterpriseName": "API" } } }
internalJSON.put("appId", EMIConfigTest.APP_ID);
internalJSON.put("switchNumber", EMIConfigTest.SWITCH_NUMBER);//總機號碼
// internalJSON.put("number", "1004");
// internalJSON.put("userData", "123456");
jsonData.put("addEnterprise", internalJSON);
return EMIAdapter.doJsonPost(EMIConfigTest.SUB_PATH + AccountEnum.EMI_SUB.getAccId() + EMIAPIEnum.ADD_ENTERPRISE.getPart(), jsonData.toString(), AccountEnum.EMI_SUB.getAccId(), AccountEnum.EMI_SUB.getToken());
case EMIAPI.CALL_CANCEL: ///CallCenter/callCancel ok
internalJSON.put("appId", EMIConfigTest.APP_ID);
internalJSON.put("workNumber", "gh1356");
internalJSON.put("callId", "api0040001355f152714300405029v5F");
jsonData.put("callCancel", internalJSON);
return EMIAdapter.doJsonPost(EMIConfigTest.SUB_PATH + AccountEnum.EMI_SUB.getAccId() + EMIAPIEnum.CALL_CANCEL.getPart(), jsonData.toString(), AccountEnum.EMI_SUB.getAccId(), AccountEnum.EMI_SUB.getToken());
case EMIAPI.CALL_DETAIL://獲取詳單 ok
internalJSON.put("appId", EMIConfigTest.APP_ID);
internalJSON.put("callId", adminInfo.getEminewCallId());
jsonData.put("callDetail", internalJSON);
logger.info("CALL_DETAIL" + jsonData.toString());
return EMIAdapter.doJsonPost(EMIConfigTest.SUP_PATH + AccountEnum.EMI_SUP.getAccId() + EMIAPIEnum.CALL_DETAIL.getPart(), jsonData.toString(), AccountEnum.EMI_SUP.getAccId(), AccountEnum.EMI_SUP.getToken());
case EMIAPI.ENTERPRISES_DROP_USER://刪除用戶 ok
internalJSON.put("appId", EMIConfigTest.APP_ID);
internalJSON.put("workNumber", adminInfo.getEmiWorkNumber());
jsonData.put("dropUser", internalJSON);
logger.info("DROP_USER" + jsonData.toString());
return EMIAdapter.doJsonPost(EMIConfigTest.SUB_PATH + AccountEnum.EMI_SUB.getAccId() + EMIAPIEnum.ENTERPRISES_DROP_USER.getPart(), jsonData.toString(), AccountEnum.EMI_SUB.getAccId(), AccountEnum.EMI_SUB.getToken());
case EMIAPI.CALL_MONITOR: //監(jiān)聽
internalJSON.put("appId", EMIConfigTest.APP_ID);
internalJSON.put("workNumber", EMIConfigTest.monitorWorkNumber);
internalJSON.put("callId", "api0040001355f153232789915845216");
jsonData.put("callMonitor", internalJSON);
logger.info("CALL_MONITOR" + jsonData.toString());
return EMIAdapter.doJsonPost(EMIConfigTest.SUB_PATH + AccountEnum.EMI_SUB.getAccId() + EMIAPIEnum.CALL_MONITOR.getPart(), jsonData.toString(), AccountEnum.EMI_SUB.getAccId(), AccountEnum.EMI_SUB.getToken());
case EMIAPI.CALL_INSERT: //監(jiān)聽
internalJSON.put("appId", EMIConfigTest.APP_ID);
internalJSON.put("workNumber", EMIConfigTest.monitorWorkNumber);
internalJSON.put("callId", "api0040001355f1532338787175l68FB");
jsonData.put("callInsert", internalJSON);
logger.info("CALL_INSERT" + jsonData.toString());
return EMIAdapter.doJsonPost(EMIConfigTest.SUB_PATH + AccountEnum.EMI_SUB.getAccId() + EMIAPIEnum.CALL_INSERT.getPart(), jsonData.toString(), AccountEnum.EMI_SUB.getAccId(), AccountEnum.EMI_SUB.getToken());
case EMIAPI.CALL_RECORD_URL: //下載
internalJSON.put("appId", EMIConfigTest.APP_ID);
internalJSON.put("callId", "api0040001355f1532337733024Z5ZjJ");
jsonData.put("callRecordUrl", internalJSON);
logger.info("CALL_RECORD_URL" + jsonData.toString());
return EMIAdapter.doJsonPost(EMIConfigTest.SUP_PATH + AccountEnum.EMI_SUP.getAccId() + EMIAPIEnum.CALL_RECORD_URL.getPart(), jsonData.toString(), AccountEnum.EMI_SUP.getAccId(), AccountEnum.EMI_SUP.getToken());
}
return null;
}
}
讀者須知:
1.本系列文章內容會比較簡陋,望有興趣讀者還是fork源碼,調試一下。(如果你看過該書,一定可以加深印象)
2.聯(lián)想下實際運用的哪些業(yè)務場景用到該模式,哪些中間件用到該模式,是否自己能在業(yè)務中使用。
3.即使你現(xiàn)在用不到某些設計模式,但是還是應該理解其原理的。
4.當時理解并不意味著自己已會,可以自己嘗試練習,并幻想一種業(yè)務場景,畫畫類圖,設計一下。
coding時,做到了如何落實;
writing時,做到了如何表達;
sharing時,做到了如何傳授;
thinking時,做到了如何提升;
代碼請參考碼云:https://gitee.com/tjhuey/CodingGroup
設計模式相關概念請參考:http://naotu.baidu.com/file/5811bf42020e6a2d877b992cfca90d26
進度
[x]
策略模式,<span style="color: #43A047; ">已完成</span>[x]
觀察者模式,<span style="color: #43A047; ">已完成</span>;[x]
裝飾者模式,<span style="color: #43A047; ">已完成</span>;[x]
工廠方法模式,<span style="color: #43A047; ">已完成</span>;[x]
抽象工廠模式,<span style="color: #43A047; ">已完成</span>;[x]
單例模式,<span style="color: #43A047; ">已完成</span>;[x]
命令模式,<span style="color: #43A047; ">已完成</span>;[x]
適配模式,<span style="color: #43A047; ">已完成</span>;[x]
外觀模式,<span style="color: #43A047; ">已完成</span>;[ ]
..,<span style="color: #F44336; ">未完成</span>;