设计模式之外观模式(门面模式)以及如何利用到接口设计中

摘要:
什么是皮肤模式?它隐藏了系统的复杂性,并为客户端提供了访问系统的接口。这种类型的设计模式是一种结构模式。简而言之,皮肤模式的应用场景是将一些复杂的过程封装到界面中,以便外部用户更容易使用。根据客户角色的要求,内部保留了几个功能组合。客户角色和外表对此一无所知。它可以在系统内进行交互,也可以为外部调用提供接口。
什么是外观模式

  外观模式(Facade),他隐藏了系统的复杂性,并向客户端提供了一个可以访问系统的接口。这种类型的设计模式属于结构性模式。为子系统中的一组接口提供了一个统一的访问接口,这个接口使得子系统更容易被访问或者使用。 

外观模式应用场景

设计模式之外观模式(门面模式)以及如何利用到接口设计中第1张

简单来说,该模式就是把一些复杂的流程封装成一个接口供给外部用户更简单的使用。这个模式中,设计到3个角色。

1.门面角色:外观模式的核心。它被客户角色调用,它熟悉子系统的功能。内部根据客户角色的需求预定了几种功能的组合。

2.子系统角色:实现了子系统的功能。它对客户角色和Facade时未知的。它内部可以有系统内的相互交互,也可以由供外界调用的接口。

3.客户角色:通过调用Facede来完成要实现的功能。

相关代码实现

需要重构代码

/**
* All rights Reserved,
* Designed By lqq
* Copyright (C) @2020
*
* @description :用户下单成功后
* 1.增加支付回调接口日志
* 2.修改订单数据库状态为已经成功
* 3.调用积分服务接口
* 4.调用消息服务平台服务接口
* @author: 963833533@qq.com lqq
* @date: Created in 2020/10/25
* @since: 2020
* @version: 1.0
*/
@Slf4j
@Component
public class PayCallbackService {
public boolean callback(Map<String, String> verifySignature) {
// 1.第一步打印日志信息
String orderId = verifySignature.get("orderId"); // 获取后台通知的数据,其他字段也可用类似方式获取
String respCode = verifySignature.get("respCode");
log.info("orderId:{},respCode:{}", orderId, respCode);
// 2.修改订单状态为已经支付
new PayTransactionMapper() {
@Override
public void updatePayStatus() {
log.info(">>>修改订单状态为已经支付>>>>>");
}
}.updatePayStatus();
// 3.调用积分接口增加积分
HttpClientUtils.doPost("jifen.com", "积分接口");
// 4.调用消息服务平台提示
HttpClientUtils.doPost("msg.com", "调用消息接口");
return true;
}
}

utils

/**
* All rights Reserved,
* Designed By lqq
* Copyright (C) @2020
*
* @description :
* @author: 963833533@qq.com lqq
* @date: Created in 2020/10/25
* @since: 2020
* @version: 1.0
*/
@Slf4j
public class HttpClientUtils {

public static String doPost(String url, String text) {
log.info(">>>Url:{},text:{}", url, text);
return "success";
}
}

创建业务逻辑封装

/**
* All rights Reserved,
* Designed By lqq
* Copyright (C) @2020
*
* @description :
* @author: 963833533@qq.com lqq
* @date: Created in 2020/10/25
* @since: 2020
* @version: 1.0
*/
@Slf4j
@Component
public class LogService {

public void log(Map<String, String> verifySignature) {
String orderId = verifySignature.get("orderId"); // 获取后台通知的数据,其他字段也可用类似方式获取
String respCode = verifySignature.get("respCode");
log.info("1.第一个模块,打印日志模块:orderId:{},respCode:{}", orderId, respCode);
}
}
/**
* All rights Reserved,
* Designed By lqq
* Copyright (C) @2020
*
* @description :
* @author: 963833533@qq.com lqq
* @date: Created in 2020/10/25
* @since: 2020
* @version: 1.0
*/
@Slf4j
@Component
public class PayService {

public void updatePayStatus() {
// 2.修改订单状态为已经支付
new PayTransactionMapper() {
@Override
public void updatePayStatus() {
log.info(2."第二个模块>>>修改订单状态为已经支付>>>>>");
}
}.updatePayStatus();
}
}
/**
* All rights Reserved,
* Designed By lqq
* Copyright (C) @2020
*
* @description :
* @author: 963833533@qq.com lqq
* @date: Created in 2020/10/25
* @since: 2020
* @version: 1.0
*/
@Component
@Slf4j
public class IntegralService {

public void callIntegral() {
// 3.调用积分接口增加积分
HttpClientUtils.doPost("jifen.com", "积分接口");
log.info("3.第三个模块>>>调用积分接口打印日志>>>>>");
}
}
/**
* All rights Reserved,
* Designed By lqq
* Copyright (C) @2020
*
* @description :
* @author: 963833533@qq.com lqq
* @date: Created in 2020/10/25
* @since: 2020
* @version: 1.0
*/
@Component
@Slf4j
public class MsgService {

public void callMsg() {
log.info("4.第四个模块 调用消息模块");
HttpClientUtils.doPost("msg.com", "调用消息接口");
}
}

创建门面接口:PayFacade

/**
* All rights Reserved,
* Designed By lqq
* Copyright (C) @2020
*
* @description :
* @author: 963833533@qq.com lqq
* @date: Created in 2020/10/25
* @since: 2020
* @version: 1.0
*/
@Component
public class PayFacade {
@Autowired
private LogService logService;
@Autowired
private PayService payService;
@Autowired
private IntegralService integralService;
@Autowired
private MsgService msgService;
public String callback(Map<String, String> verifySignature) {
logService.log(verifySignature);
payService.updatePayStatus();
integralService.callIntegral();
msgService.callMsg();
return "success";
}
}

PayCallbackController 

/**
* All rights Reserved,
* Designed By lqq
* Copyright (C) @2020
*
* @description :
* @author: 963833533@qq.com lqq
* @date: Created in 2020/10/25
* @since: 2020
* @version: 1.0
*/
@RestController
public class PayCallbackController {
@Autowired
private PayFacade payFacade;

@RequestMapping("/callback")
public String callback(@RequestBody Map<String, String> verifySignature) {
String result = payFacade.callback(verifySignature);
return result;
}
}

mapper

/**
* All rights Reserved,
* Designed By lqq
* Copyright (C) @2020
*
* @description :
* @author: 963833533@qq.com lqq
* @date: Created in 2020/10/25
* @since: 2020
* @version: 1.0
*/
public interface PayTransactionMapper {
void updatePayStatus();
}

启动类

/**
* All rights Reserved,
* Designed By lqq
* Copyright (C) @2020
*
* @description :
* @author: 963833533@qq.com lqq
* @date: Created in 2020/10/25
* @since: 2020
* @version: 1.0
*/
@SpringBootApplication
public class AppFacade {
public static void main(String[] args) {
SpringApplication.run(AppFacade.class);
}
}

相关依赖

    <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<dependencies>
<!-- sprinboot web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<dependency>
<groupId>commons-lang3</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>

</dependencies>

优点

松散耦合:使得客户端和子系统之间解耦,让子系统内部的模块功能更容易扩展和维护;

简单易用:客户端根本不需要知道子系统内部的实现,或者根本不需要知道子系统内部的构成,它只需要跟Facade类交互即可。

更好的划分访问层次:有些方法是对系统外的,有些方法是系统内部相互交互的使用的。子系统把那些暴露给外部的功能集中到门面中,这样就可以实现客户端的使用,很好的隐藏了子系统内部的细节。

控制台输出

免责声明:文章转载自《设计模式之外观模式(门面模式)以及如何利用到接口设计中》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇qtopia 文件系统启动过程分析一文解读裸金属云 (转)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

几句话说清楚m.2和AHCI、NVME

【简单解说】 M是一代mini硬件接口,如MSATA,M.2是二代mini硬件接口,如M.2 NVME/SATA,  M.2支持传统SATA和PCI Express存储设备 M.2更多的指的是主板上的硬件接口(M.2接口,是Intel推出的一种替代MSATA新的接口规范,也就是我们以前经常提到的NGFF,即Next Generation Form Fact...

Android okHttp网络请求之Retrofit+Okhttp+RxJava组合

Retrofit介绍:   Retrofit和okHttp师出同门,也是Square的开源库,它是一个类型安全的网络请求库,Retrofit简化了网络请求流程,基于OkHtttp做了封装,解耦的更彻底:比方说通过注解来配置请求参数,通过工厂来生成CallAdapter,Converter,你可以使用不同的请求适配器(CallAdapter), 比方说RxJ...

java UUID

UUID.randomUUID().toString().replaceAll("-", ""); UUID UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,是一种软件建构的标准,亦为开放软件基金会组织在分布式计算环境领域的一部分。 作用 UUID 的目的是让分布式系统中的所有元素,都能有唯一的辨识资讯,而...

Jmeter之Bean shell使用(一)

一、什么是Bean Shell BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法; BeanShell是一种松散类型的脚本语言(这点和JS类似); BeanShell是用Java写成的,一个小型的、免费的、可以下载的、嵌入式的Java源代码解释器,具有对象脚本语言特性,非常精简的解释器jar文件大小为175k。...

写一个播放视频文件的ActiveX控件——MFC版(原创)

    介于自己的ATL学的不怎么样,而且现在掌握的也不是很熟练,所以还是先用MFC来写一个播放视频的ActiveX控件吧。用MFC做ActiveX控件非常简单,和用MFC做普通的Windows应用程序差不多是一样的步骤。所以,如果用过MFC的话,开发起来会非常的顺手。不过了,MFC是已经快过时了,不过在中国暂时还没有过时。还有一个问题,MFC做的界面非...

基于 .NET 的 FluentValidation 验证教程

FluentValidation 是一个基于 .NET 开发的验证框架,开源免费,而且优雅,支持链式操作,易于理解,功能完善,还是可与 MVC5、WebApi2 和 ASP.NET CORE 深度集成,组件内提供十几种常用验证器,可扩展性好,支持自定义验证器,支持本地化多语言。 虽然 FluentValidation 是一个非常强大的验证框架,但针对该框...