设计模式之(七):外观设计模式

外观模式章节概要

一.定义

提供一个统一的接口,用来访问子系统的一群接口(也称门面模式)

简单来说:有一个统一的对外口径,它的实现可能调用了很多子系统的接口

二.适用场景

  • 子系统越来越复杂,增加外观模式提供简单调用接口
  • 构建多层系统结构,利用外观对象作为每层的入口,简化层间调用

三.优缺点

1.优点
  • 简化调用过程,无需了解、深入子系统,防止带来风险
  • 减少系统依赖、松散耦合
  • 更好的划分访问层次
2.缺点
  • 增加子系统、扩展子系统行为容易引入风险

四.角色

  • 1.外观对象(可能包含接口和具体实现类)
  • 2.子系统服务对象

五.实例

交易系统中一个取消订单的接口,它可能涉及很多操作,但客户端只需要调用取消订单即可,其他细节,它不需要关心

1.订单数据实体
  1. package com.shixinke.practise.design.pattern.content.structural.facade;
  2. import java.math.BigDecimal;
  3. /**
  4. * 订单实体
  5. * @author shixinke
  6. */
  7. public class Order {
  8. /**
  9. * 订单ID
  10. */
  11. private Long orderId;
  12. /**
  13. * 用户
  14. */
  15. private Long userId;
  16. /**
  17. * 支付方式
  18. */
  19. private Short payment;
  20. /**
  21. * 金额
  22. */
  23. private BigDecimal amount;
  24. /**
  25. * 订单状态(这里为了简单,不将物流状态/支付状态等分开)
  26. */
  27. private Short status;
  28. public Long getOrderId() {
  29. return orderId;
  30. }
  31. public void setOrderId(Long orderId) {
  32. this.orderId = orderId;
  33. }
  34. public Long getUserId() {
  35. return userId;
  36. }
  37. public void setUserId(Long userId) {
  38. this.userId = userId;
  39. }
  40. public Short getPayment() {
  41. return payment;
  42. }
  43. public void setPayment(Short payment) {
  44. this.payment = payment;
  45. }
  46. public BigDecimal getAmount() {
  47. return amount;
  48. }
  49. public void setAmount(BigDecimal amount) {
  50. this.amount = amount;
  51. }
  52. public Short getStatus() {
  53. return status;
  54. }
  55. public void setStatus(Short status) {
  56. this.status = status;
  57. }
  58. /*
  59. * 订单状态定义
  60. */
  61. public enum Status {
  62. UNPAID(Short.valueOf("1")),
  63. PAID(Short.valueOf("2"));
  64. private Short value;
  65. Status(Short value) {
  66. this.value = value;
  67. }
  68. public Short getValue() {
  69. return value;
  70. }
  71. }
  72. }
2.接口响应实体
  1. /**
  2. * 接口响应类
  3. * @author shixinke
  4. */
  5. public class ResponseDTO<T> {
  6. /**
  7. * 状态码
  8. */
  9. private Integer code;
  10. /**
  11. * 提示信息
  12. */
  13. private String message;
  14. /**
  15. * 是否成功
  16. */
  17. private boolean success;
  18. /**
  19. * 数据体
  20. */
  21. private T data;
  22. public ResponseDTO(Integer code, String message, boolean success, T data) {
  23. this.code = code;
  24. this.message = message;
  25. this.success = success;
  26. this.data = data;
  27. }
  28. public Integer getCode() {
  29. return code;
  30. }
  31. public void setCode(Integer code) {
  32. this.code = code;
  33. }
  34. public String getMessage() {
  35. return message;
  36. }
  37. public void setMessage(String message) {
  38. this.message = message;
  39. }
  40. public boolean isSuccess() {
  41. return success;
  42. }
  43. public void setSuccess(boolean success) {
  44. this.success = success;
  45. }
  46. public T getData() {
  47. return data;
  48. }
  49. public void setData(T data) {
  50. this.data = data;
  51. }
  52. public static ResponseDTO error(int code, String message) {
  53. return new ResponseDTO(code, message, false, null);
  54. }
  55. public static <T> ResponseDTO success(T data) {
  56. return new ResponseDTO(200, "success", true, data);
  57. }
  58. }
3.订单子服务
(1)订单服务接口
  1. /**
  2. * 订单服务接口
  3. * @author shixinke
  4. */
  5. public interface OrderService {
  6. /**
  7. * 获取订单信息
  8. * @param orderId
  9. * @return
  10. */
  11. Order getOrder(Long orderId);
  12. /**
  13. * 取消订单
  14. * @param orderId
  15. * @return
  16. */
  17. boolean cancelOrder(Long orderId);
  18. }
(2)订单服务实现
  1. /**
  2. * 订单服务(实现)
  3. * @author shixinke
  4. */
  5. public class OrderServiceImpl implements OrderService {
  6. /**
  7. * 获取订单
  8. * @param orderId
  9. * @return
  10. */
  11. public Order getOrder(Long orderId) {
  12. /**
  13. * 查询操作
  14. */
  15. Order order = new Order();
  16. return order;
  17. }
  18. /**
  19. * 取消订单操作
  20. * @param orderId
  21. * @return
  22. */
  23. public boolean cancelOrder(Long orderId) {
  24. System.out.println("修改订单状态,将订单修改为已取消");
  25. return true;
  26. }
  27. }
4.支付子系统
(1)支付服务接口
  1. /**
  2. * 支付服务
  3. * @author shixinke
  4. */
  5. public interface PaymentService {
  6. /**
  7. * 退款
  8. * @param userId 用户
  9. * @param amount 金额
  10. * @return
  11. */
  12. boolean refund(Long userId, BigDecimal amount);
  13. }
(2)支付服务实现
  1. /**
  2. * 支付服务
  3. * @author shixinke
  4. */
  5. public class PaymentServiceImpl implements PaymentService {
  6. /**
  7. * 退款
  8. * @param userId 用户
  9. * @param amount 金额
  10. * @return
  11. */
  12. public boolean refund(Long userId, BigDecimal amount) {
  13. System.out.println("发起退款操作");
  14. return true;
  15. }
  16. }
5.订单对外服务(外观类)
(1)外观类服务接口
  1. /**
  2. * 订单对外接口
  3. * @author shixinke
  4. */
  5. public interface OrderFacade {
  6. /**
  7. * 取消订单
  8. * @param orderId
  9. * @param userId
  10. * @return
  11. */
  12. ResponseDTO cancelOrder(Long orderId, Long userId);
  13. }
(2)外观类服务实现
  1. /**
  2. * 订单(实现)
  3. */
  4. public class OrderFacadeImpl implements OrderFacade {
  5. /**
  6. * 取消订单
  7. * @param orderId
  8. * @param userId
  9. * @return
  10. */
  11. public ResponseDTO cancelOrder(Long orderId, Long userId) {
  12. /**
  13. * 1.获取订单信息
  14. */
  15. OrderService orderService = new OrderServiceImpl();
  16. Order order = orderService.getOrder(orderId);
  17. if (order == null) {
  18. return ResponseDTO.error(404, "订单不存在");
  19. }
  20. /**
  21. * 订单所属用户判断(查看是否有权限)
  22. */
  23. if (!order.getUserId().equals(userId)) {
  24. return ResponseDTO.error(401, "订单不存在");
  25. }
  26. /**
  27. * 订单状态判断(哪些状态不能取消)
  28. */
  29. /**
  30. * 2.取消订单操作
  31. */
  32. boolean result = orderService.cancelOrder(orderId);
  33. if (!result) {
  34. return ResponseDTO.error(500, "订单取消失败");
  35. }
  36. /**
  37. * 退款操作(可以是通过异步MQ,或同步操作方法,记录日志等)
  38. */
  39. boolean needRefund = true; //哪些状态需要退款
  40. if (needRefund) {
  41. PaymentService paymentService = new PaymentServiceImpl();
  42. boolean refundResult = paymentService.refund(userId, order.getAmount());
  43. if (!refundResult) {
  44. //退款失败的操作,回滚或者其他
  45. }
  46. }
  47. return ResponseDTO.success(null);
  48. }
  49. }

以上类的UML关系图:
外观模式UML图