在最近一期影片什麼是大型專案裡舉了一個?,說是高階開發重構了業務通知這塊邏輯,有好幾位粉絲對具體的程式碼實現比較好奇,我臨時自己手寫了一份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 協議》,轉載必須註明作者和本文連結