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

可擴展 Java 應用開發模式實戰:命令、中介者、觀察者模式重構臃腫事件處理

     編輯:Java 相關知識

痛點:主類膨脹的事件處理

初學者常將所有監聽邏輯塞入主 JFrame/JPanel:actionPerformed 中大量 if (e.getSource() == btnX) 判斷,導致類職責不清、難擴展、難測試。本文以「游泳隊員性別篩選」為例,逐步重構為高內聚低耦合的架構。

領域模型

public class Swimmer {
    private String name; private int age; private String club; private boolean female;
    // 構造器、getter、isFemale()...
}

public class Swimmers { // 集合類
    private Vector<Swimmer> kids = new Vector<>();
    public Vector<Swimmer> getList(boolean female) { /* 篩選邏輯 */ }
    public Vector<Swimmer> getList() { /* 全部 */ }
}

重構演進四階段

階段 1:命令模式 — 將行為封裝到按鈕

public interface Command { void execute(); }

public abstract class SexButton extends JRadioButton implements Command {
    protected Swimmers swimmers; protected Mediator mediator; // 階段2引入
    public SexButton(String title, Swimmers s, Mediator m, ActionListener al) {
        super(title); this.swimmers=s; this.mediator=m; addActionListener(al);
    }
    public abstract void execute();
}

public class FemaleButton extends SexButton {
    public void execute() { mediator.loadList(swimmers.getList(true)); }
}
// MaleButton, BothButton 同理

主類監聽器極簡:

public void actionPerformed(ActionEvent e) {
    ((Command) e.getSource()).execute(); // 多態分發,無 if-else
}

階段 2:中介者模式 — 解耦按鈕與列表組件

按鈕不再直接持有 JList 引用,改為依賴 Mediator:

public class Mediator {
    private JawList kidList; // 封裝 JList 的視圖組件
    public void loadList(Vector<Swimmer> v) {
        kidList.clear();
        for (Swimmer s : v) kidList.add(s.getName());
    }
}

按鈕僅調用 mediator.loadList(...),視圖變更 (如換成表格) 僅修改 Mediator。

階段 3:模板方法模式 — 統一按鈕創建流程

SexButton 構造器封裝公共初始化 (添加監聽器、保存依賴),子類只實現 execute(),符合「好萊塢原則」。

階段 4:觀察者模式 — 數據模型驅動視圖自動更新

public class JListData extends AbstractListModel {
    private Vector<String> data = new Vector<>();
    public void addElement(String s) { data.add(s); fireIntervalAdded(this, data.size()-1, data.size()); }
    public void clear() { int sz=data.size(); data.clear(); fireIntervalRemoved(this,0,sz); }
    // getSize, getElementAt...
}

public class JawList extends JScrollPane {
    private JListData listContents = new JListData();
    private JList list = new JList(listContents);
    // add/remove/clear 代理到 listContents
}

優勢:數據變更自動通知視圖,按鈕/中介者僅操作 JListData,完全不感知 JList 存在。

架構對比總結

模式解決問題關鍵角色適用場景
命令消除巨大的 actionPerformed 分發Command 接口、具體命令類菜單項、工具欄、按鈕動作
中介者解耦多個交互組件 (按鈕、列表、表單)Mediator、Colleague複雜對話框、向導、多視圖聯動
模板方法固定算法骨架,延遲具體步驟到子類抽象基類、鉤子方法框架擴展點、向導步驟
觀察者數據模型與視圖分離,自動同步Subject/Observable、ObserverMVC/MVP、綁定框架基礎

最佳實踐建議

  • **從命令模式起步**:最小改動即可消除 if-else 地獄。
  • **引入中介者**當組件間耦合超過 2 層時。
  • **數據模型繼承 AbstractListModel/TableModel**:免費獲得觀察者機制,Swing 設計初衷。
  • **依賴注入構建關係**:主類組裝 Command、Mediator、Model、View,而非反向查找。

結語

設計模式非理論裝飾,而是解決具體耦合痛點的工具。通過命令+中介者+觀察者組合,將百行臃腫主類拆分為單一職責的類群,實現「開閉原則」:新增篩選條件只需添加新 Button 類,零修改現有代碼。

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