前言:
前沿技术一直在迭代,有一种东西是不会更新的,那就是设计模式的思想。 可以来学习学习设计模式的思维,巧妙设计!
外观模式就是整合多个对象到一个对象,对外暴露一个,常用接口简化!
适配模式,简单的说是接口转化,将不符合,不对外的接口转化符合,对外而已。
[TOC]
1.官方话语
概述
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
六大原则:
单一职责原则 (Single ResponsiBility Principle) 概括:应该有且仅有一个原因引起类的变更
里氏替换原则(liskov Substitution Principle ) 概括:基类出现的地方,子类一定可以出现
依赖倒转原则(Depndece Inversion Principle) 概括:针对接口编程,依赖于抽象而不是具体
接口隔离原则(Interface Segregation Principle) 概括:使用多个隔离的接口,比使用单个接口好 (细分接口,降低耦合)
迪米特法则 (Demeter Principle) 概括:实体应当尽量少的与其他类发生互相作用,使得系统功能模块相对独立
开闭原则(Open Close Principle) 概括: 对扩展开放,对修改关闭
合成复用原则 (Composite Reuse Principle) 概括:尽量使用合成/聚合的方式,少用继承
个人话语
概述
设计模式在代码层级中,是让你在某种业务场景刚开始设计时,能让未来的相关需求扩展
极为方便的一个思想。
简单的说,在一开始设计好,扩展是很方便的,设计模式就是这个功劳者
。
对于我们本来就懒的开发人员来说,这是求之不得
的。
六大原则
而对于六大原则,简单过一下就行,不用刻意理解,如果你会了面向对象和设计模式的使用
,自然就遵循了。
今日主题
适配模式:将一个类的接口变换成客户端所期待的另一种接口,从而使本因接口不匹配而无法在一起工作的两个类能够在一起工作。
外观模式:要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行,外观模式提供一个高层次的接口,使得子系统更易于使用
场景:
这次我引入了一个我实际的案例,具体看码云 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() {
/**
*创建适配器对象
*/
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");
}
}
'业务中三方对接使用适配,外观,策略等思想'部分代码
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 写个大接口,方便测试和调用 欠优化
* @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: //创建坐席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: //监听
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: //监听
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.联想下实际运用的哪些业务场景用到该模式,哪些中间件用到该模式,是否自己能在业务中使用。
3.即使你现在用不到某些设计模式,但是还是应该理解其原理的。
4.当时理解并不意味着自己已会,可以自己尝试练习,并幻想一种业务场景,画画类图,设计一下。
coding
时,做到了如何落实
;
writing
时,做到了如何表达
;
sharing
时,做到了如何传授
;
thinking
时,做到了如何提升
;
代码请参考码云:https://gitee.com/tjhuey/CodingGroup
设计模式相关概念请参考:http://naotu.baidu.com/file/5811bf42020e6a2d877b992cfca90d26
进度
[x]
策略模式
,已完成[x]
观察者模式
,已完成;[x]
装饰者模式
,已完成;[x]
工厂方法模式
,已完成;[x]
抽象工厂模式
,已完成;[x]
单例模式
,已完成;[x]
命令模式
,已完成;[x]
适配模式
,已完成;[x]
外观模式
,已完成;[ ]
..
,未完成;