觀察者+配置中心動態策略路由Demo

邢闖洋發表於2021-12-03

在最近一期影片什麼是大型專案裡舉了一個?,說是高階開發重構了業務通知這塊邏輯,有好幾位粉絲對具體的程式碼實現比較好奇,我臨時自己手寫了一份Demo,可以供大家參考一下,跟教科書的觀察者和策略模式有些變化,能解決問題是重點,具體就不講解了,都在註釋裡。

當然,這裡繼續留一點作業給大家 :

執行的順序怎麼去定義和實現?

單個通知失敗了怎麼辦?

選不同的元件當配置中心有何區別?

增加一種新的傳送渠道怎麼辦?

如果大批次短時間傳送,有哪些地方可以最佳化?

import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: @極海Channel
 * @Date:2021/12/2
 * @Description:
 */
@SpringBootApplication
public class ObserverDemo implements CommandLineRunner {

    /** 這裡可以註冊多個觀察者,這個demo只註冊了一個訊息通知 */
    @Autowired
    List<Observer> observerList;

    public static void main(String[] args) {
        new SpringApplication(ObserverDemo.class).run(args);
    }

    /** 容器啟動即執行 */
    @Override
    public void run(String... args) {
        sendMsg("bizType1", "業務1的內容");
        sendMsg("bizType2", "業務2的內容");
    }
    /** client呼叫,指明業務和需要傳送的內容 */
    private void sendMsg(String bizType, String content) {
        observerList.forEach(observer -> observer.notify(bizType, content));
    }
}

/**
 * 觀察者,JDK自帶有觀察者,定義介面不指定實現
 */
interface Observer {

    void notify(String bizType, String content);
}

/**
 * 傳送訊息的觀察者, 也實現了傳送策略的組合和選擇
 */
@Component
class SendMsgObserver implements Observer {

    /** 所有傳送實現,均可見*/
    @Autowired
    private List<SendMsgService> sendMsgServices;

    @Override
    public void notify(String bizType, String content) {
        // 獲取業務型別 -> 策略組合
        List<String> strategy = ConfigCenter.getStrategy(bizType);
        sendMsgServices.forEach(sendMsgService -> {
            // 配置的策略在內,傳送
            if (strategy.contains(sendMsgService.getClass().getDeclaredAnnotation(Service.class).value())) {
                sendMsgService.sendMsg(content);
            }
        });
    }
}

/**
 * 模擬配置中心, nacos/zookeeper/redis/MySQL等均可。
 */
class ConfigCenter {
    private static Map<String, String> sendMsgConfig = new HashMap<>();
    static {
        sendMsgConfig.put("bizType1", "email,sms");
        sendMsgConfig.put("bizType2", "sms");
    }
    // 根據業務獲取配置,新業務,配置key-value即可
    public static List<String> getStrategy(String bizType) {
        return Lists.newArrayList(sendMsgConfig.get(bizType).split(","));
    }
}

/**
 * 傳送訊息的能力抽象,可以理解為策略介面
 */
interface SendMsgService {
    /** 傳送內容*/
    void sendMsg(String content);
}

/**
 * 兩種傳送方式實現
 */
@Service("sms")
class SmsSendService implements SendMsgService {
    @Override
    public void sendMsg(String content) {
        System.out.println("簡訊傳送:" + content);
    }
}
@Service("email")
class EmailSendService implements SendMsgService {
    @Override
    public void sendMsg(String content) {
        System.out.println("郵件傳送:" + content);
    }
}

作者:極海Channel www.bilibili.com/read/cv14249669?s... 出處:bilibili

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章