《讀_Head_First_有感》_“適配&外觀模式”

前言:

前沿技術一直在迭代,有一種東西是不會更新的,那就是設計模式的思想。 可以來學習學習設計模式的思維,巧妙設計!

外觀模式就是整合多個對象到一個對象,對外暴露一個,常用接口簡化!

適配模式,簡單的說是接口轉化,將不符合,不對外的接口轉化符合,對外而已。

[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>;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容