真實案例實戰——設計模式之【外觀模式(門面模式)】

寫在前面:設計模式源於生活,而又高於生活!

什麼是外觀模式

  外觀模式(Facade),他隱藏了系統的複雜性,並向客戶端提供了一個能夠訪問系統的接口。這種類型的設計模式屬於結構性模式。爲子系統中的一組接口提供了一個統一的訪問接口,這個接口使得子系統更容易被訪問或者使用。 web

外觀模式應用場景

簡單來講,該模式就是把一些複雜的流程封裝成一個接口供給外部用戶更簡單的使用。這個模式中,設計到3個角色。spring

1.門面角色:外觀模式的核心。它被客戶角色調用,它熟悉子系統的功能。內部根據客戶角色的需求預約了幾種功能的組合。數據庫

2.子系統角色:實現了子系統的功能。它對客戶角色和Facade時未知的。它內部能夠有系統內的相互交互,也能夠由供外界調用的接口。設計模式

3.客戶角色:經過調用Facede來完成要實現的功能。app

相關代碼實現

須要重構代碼ide

@Slf4j
@Component
public class PayCallbackService {
    // 用戶下單成功後,有那些操做?
    // 1.增長支付回調接口日誌
    // 2.修改訂單數據庫狀態爲已經成功
    // 3.調用積分服務接口
    // 4.調用消息服務平臺服務接口

    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 PaymentTransactionMapper() {
            @Override
            public void updatePaymentStatus() {
                log.info(">>>修改訂單狀態爲已經支付>>>>>");
            }
        }.updatePaymentStatus();
        // 3.調用積分接口增長積分
        HttpClientUtils.doPost("jifen.com", "積分接口");
        // 4.調用消息服務平臺提示
        HttpClientUtils.doPost("msg.com", "調用消息接口");
        return true;
    }
}

utilsspring-boot

@Slf4j
public class HttpClientUtils {

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

建立業務邏輯封裝post

@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);
    }
}
@Slf4j
@Component
public class PaymentService {

    public void updatePaymentStatus() {
        // 2.修改訂單狀態爲已經支付
        new PaymentTransactionMapper() {
            @Override
            public void updatePaymentStatus() {
                log.info(2."第二個模塊>>>修改訂單狀態爲已經支付>>>>>");
            }
        }.updatePaymentStatus();
    }
}
@Component
@Slf4j
public class IntegralService {

    public void callIntegral() {
        // 3.調用積分接口增長積分
        HttpClientUtils.doPost("jifen.com", "積分接口");
        log.info("3.第三個模塊>>>調用積分接口打印日誌>>>>>");
    }
}
@Component
@Slf4j
public class MsgService {

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

建立門面接口:PayFacade 測試

@Component
public class PayFacade {
    @Autowired
    private LogService logService;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private IntegralService integralService;
    @Autowired
    private MsgService msgService;

    public String callback(Map<String, String> verifySignature) {
        logService.log(verifySignature);
        paymentService.updatePaymentStatus();
        integralService.callIntegral();
        msgService.callMsg();
        return "success";
    }
}

PayCallbackController url

@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

public interface PaymentTransactionMapper {
    void updatePaymentStatus();
}

啓動類

@SpringBootApplication
public class AppFacade {
    public static void main(String[] args) {
        SpringApplication.run(AppFacade.class);
    }
}

pom

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.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.16.10</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>

    </dependencies>

使用postman進行測試

控制檯輸出

2019-05-25 23:12:54.773  INFO 1948 --- [nio-8080-exec-6] com.xuyu.service.LogService              : 1.第一個模塊,打印日誌模塊:orderId:111,respCode:xuyucode
2019-05-25 23:12:54.774  INFO 1948 --- [nio-8080-exec-6] com.xuyu.service.PaymentService          : 2.第二個模塊>>>修改訂單狀態爲已經支付>>>>>
2019-05-25 23:12:54.775  INFO 1948 --- [nio-8080-exec-6] com.xuyu.service.IntegralService         : 3.第三個模塊 調用積分模塊
2019-05-25 23:12:54.775  INFO 1948 --- [nio-8080-exec-6] com.xuyu.utils.HttpClientUtils           : >>>Url:jifen.com,text:積分接口
2019-05-25 23:12:54.775  INFO 1948 --- [nio-8080-exec-6] com.xuyu.service.MsgService              : 4.第四個模塊 調用消息模塊
2019-05-25 23:12:54.775  INFO 1948 --- [nio-8080-exec-6] com.xuyu.utils.HttpClientUtils           : >>>Url:msg.com,text:調用消息接口
success
 

優勢

鬆散耦合:使得客戶端和子系統之間解耦,讓子系統內部的模塊功能更容易擴展和維護;

簡單易用:客戶端根本不須要知道子系統內部的實現,或者根本不須要知道子系統內部的構成,它只須要跟Facade類交互便可。

更好的劃分訪問層次:有些方法是對系統外的,有些方法是系統內部相互交互的使用的。子系統把那些暴露給外部的功能集中到門面中,這樣就能夠實現客戶端的使用,很好的隱藏了子系統內部的細節。

版權@須臾之餘https://my.oschina.net/u/3995125

本文參考:螞蟻課堂:http://www.mayikt.com

相關文章
相關標籤/搜索