首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

設計模式實戰:Spring 框架下觀察者模式的優雅實現與解耦實踐

     編輯:Java 相關知識

在企業級應用開發中,業務模塊間常存在「一處觸發、多方響應」的鬆耦合需求。觀察者模式是解決此類問題的經典方案,而 Spring 容器的依賴注入(DI)與 Bean 管理機制,能將觀察者模式的靈活性提升到新高度。本文基於真實專案經驗,展示如何在 Spring 中優雅落地觀察者模式,實現業務模塊零代碼修改的動態訂閱與發布。

業務場景與設計挑戰

系統中存在功能點 A,其業務操作需觸發 B、C、D 等相關功能點進行數據同步處理。但客戶採購的功能模塊各不相同:有的客戶只有 B、D,缺少 C。傳統硬編碼調用會導致:

  • 模塊間強耦合,新增/刪除響應方需修改核心代碼
  • 部署包因客戶差異產生多版本,維護成本高
  • 違反開閉原則,擴展性差

觀察者模式天然契合:Subject(被觀察者) 維護 Observer(觀察者) 列表,狀態變更時統一通知。但傳統實現中 Observer 列表往往硬編碼在代碼或配置文件中,變更仍需重啟或改代碼。

Spring 化觀察者模式架構設計

1. 抽象觀察者角色

public abstract class StaffingObserver {
    /**
     * 統一更新入口,參數攜帶業務上下文
     * @param para 業務參數 Map,靈活擴展
     */
    public abstract void update(Map para) throws BaseException;
}

2. 具體觀察者實現(示例:終止派遣處理)

public class TerminateDispatch extends StaffingObserver {

    private DispatchDAO dispatchDAO;  // Spring 注入依賴

    @Override
    public void update(Map para) throws BaseException {
        // 具體業務邏輯:根據 para 參數執行終止派遣相關操作
        // dispatchDAO.xxx(...)
    }

    public void setDispatchDAO(DispatchDAO dispatchDAO) {
        this.dispatchDAO = dispatchDAO;
    }
}

關鍵點:觀察者作為普通 Spring Bean,享受完整 DI 能力,可注入 DAO、Service 等依賴,業務邏輯完整保留。

3. 目標角色:Spring 管理的通知分發器

public class StaffingObservable {

    private List allConfig;  // 觀察者 Bean 名稱列表,由 Spring 注入

    /**
     * 遍歷配置列表,從 Spring 容器獲取 Observer 實例並通知
     */
    public void notifyForList(Map para) throws BaseException {
        Iterator it = allConfig.iterator();
        while (it.hasNext()) {
            String beanName = it.next();
            StaffingObserver observer = (StaffingObserver) getBean(beanName);
            if (observer != null) {
                observer.update(para);
            } else {
                log.warn("Observer bean '{}' does not exist.", beanName);
            }
        }
    }

    private Object getBean(String beanName) {
        return TbApplicationContext.getWac().getBean(beanName);  // 獲取 WebApplicationContext
    }

    public void setAllConfig(List allConfig) {
        this.allConfig = allConfig;
    }
}

TbApplicationContext 為項目通用的 Spring 容器持有工具類,實現 ApplicationContextAware 靜態獲取上下文。

4. Spring XML 配置裝配(核心解耦點)

步驟一:定義具體觀察者 Bean

```xml ```

步驟二:在客戶端配置中裝配 Observable 並注入觀察者列表

```xml terminateDispatch terminateParttime ```

架構優勢與權衡

維度傳統觀察者模式Spring 化觀察者模式
觀察者註冊代碼硬編碼 subject.addObserver()Spring XML/註解配置,熱插拔
依賴管理觀察者自行查找/構建依賴容器統一 DI,生命週期托管
客戶差異化多版本代碼/配置文件同一代碼庫,不同 XML 裝配組合
新增響應方修改 Subject 代碼重編譯部署僅需新增 Bean 定義 + XML 添加一行
調試難度調用棧清晰間接調用,需良好命名與文檔輔助

最佳實踐建議

  1. 命名規範:Observer Bean 命名遵循 [BusinessAction][Domain]Observer,如 TerminateDispatchObserver,配置列表可讀性強。
  2. 異常隔離:notifyForList 中單個 Observer 異常不應阻斷後續通知,建議 try-catch 包裹並記錄錯誤日誌。
  3. 異步化擴展:引入 @Async 或 ApplicationEventPublisher 實現非阻塞通知,提升主流程響應速度。
  4. 註解驅動替代 XML:Spring 3+ 可用 @Component + @Autowired List<StaffingObserver> observers 自動收集所有實現類,進一步簡化配置。
  5. 文檔化:維護觀察者職責矩陣表,記錄每個 Observer 處理的業務場景、輸入參數、副作用,降低新人上手成本。

現代化替代:Spring Event 機制

Spring 內建 ApplicationEvent + ApplicationListener 實現了標準觀察者模式,更輕量:

// 事件定義
public class StaffingEvent extends ApplicationEvent {
    private Map data;
    public StaffingEvent(Object source, Map data) { super(source); this.data = data; }
    public Map getData() { return data; }
}

// 發布者
@Service
public class StaffingService {
    @Autowired ApplicationEventPublisher publisher;
    public void doBusiness() {
        // ...
        publisher.publishEvent(new StaffingEvent(this, params));
    }
}

// 監聽者(自動註冊)
@Component
public class TerminateDispatchListener implements ApplicationListener {
    @Override public void onApplicationEvent(StaffingEvent event) {
        // 處理邏輯
    }
}

優勢:零配置自動發現、支援異步 @EventListener、有序 @Order、泛型事件類型安全。建議新專案優先考慮 Spring Event,舊專案遷移時可共存。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved