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

Swing 架構深度剖析:MVC 模式在 JFC 組件中的創新實踐

     編輯:Java 相關知識

Java Foundation Classes (JFC) 的 Swing 組件庫將 MVC(Model-View-Controller)設計模式從應用層下沉到單個 UI 組件級別,這一創新使 JTable、JTree、JComboBox 等複雜組件擁有極高的靈活性與可擴展性。本文通過 JButton 的完整源碼級分析,揭示 Swing 如何將 MVC 三要素解耦並動態重組。

Swing 組件級 MVC 架構

傳統 MVC 用於整個應用分層,Swing 創新性地將其應用於單個組件:

  • Model:封裝組件狀態與核心邏輯(如 ButtonModel 管理 pressed/armed/selected 三態)
  • View/Controller:合併為 UI 對象(如 ButtonUI),負責渲染與事件轉換
  • 組件類:作為膠水層(如 JButton),聚合 Model 與 UI,提供統一編程接口

ButtonModel:狀態管理核心

ButtonModel 維護三種布爾狀態,定義精確的交互語義:


// 核心狀態字段
private boolean boolPressed = false;  // 鼠標按下未釋放
private boolean boolArmed = false;    // 按下且鼠標在組件內
private boolean boolSelected = false; // 切換型按鈕的選中狀態

// 狀態變更通知機制
public void setPressed(boolean boolPressed) {
    this.boolPressed = boolPressed;
    fireChangeEvent(new ChangeEvent(button)); // 通知所有 ChangeListener
}

// 事件監聽器管理
private Vector vectorChangeListeners = new Vector();
public void addChangeListener(ChangeListener l) {
    vectorChangeListeners.addElement(l);
}
protected void fireChangeEvent(ChangeEvent e) {
    Enumeration enum = vectorChangeListeners.elements();
    while (enum.hasMoreElements()) {
        ((ChangeListener)enum.nextElement()).stateChanged(e);
    }
}

ButtonUI:外觀與交互轉換

UI 對象不維護狀態,可被多組件共享,通過 installUI/uninstallUI 管理事件監聽器:


// 渲染邏輯
public void paint(Button button, Graphics g) {
    Dimension d = button.getSize();
    Color c = button.getBackground();
    g.setColor(c);
    g.fillRect(0, 0, d.width, d.height);
}

// 事件監聽器安裝/卸載
public void installUI(Button button) {
    button.addMouseListener(buttonUIListener);
    button.addMouseMotionListener(buttonUIListener);
    button.addChangeListener(buttonUIListener);
}
public void uninstallUI(Button button) {
    button.removeMouseListener(buttonUIListener);
    button.removeMouseMotionListener(buttonUIListener);
    button.removeChangeListener(buttonUIListener);
}

ButtonUIListener:語義事件轉換器

將底層 AWT 事件轉換為模型可理解的高級語義事件:


public void mousePressed(MouseEvent e) {
    Button button = (Button)e.getSource();
    ButtonModel model = button.getModel();
    model.setPressed(true);
    model.setArmed(true);
}
public void mouseDragged(MouseEvent e) {
    Button button = (Button)e.getSource();
    ButtonModel model = button.getModel();
    if (model.isPressed()) {
        model.setArmed(button.getUI().contains(button, e.getPoint()));
    }
}
public void mouseReleased(MouseEvent e) {
    Button button = (Button)e.getSource();
    ButtonModel model = button.getModel();
    model.setPressed(false);
    model.setArmed(false);
    // 此處觸發 ActionEvent 由模型內部邏輯完成
}
public void stateChanged(ChangeEvent e) {
    ((Button)e.getSource()).repaint(); // 狀態變更觸發重繪
}

動態重組能力展示

JButton 運行時可動態替換 Model 與 UI,實現熱插拔:


public void setModel(ButtonModel newModel) {
    if (this.model != null) {
        this.model.removeChangeListener(changeListener);
        this.model.removeActionListener(actionListener);
    }
    this.model = newModel;
    if (this.model != null) {
        changeListener = new ButtonChangeListener();
        actionListener = new ButtonActionListener();
        this.model.addChangeListener(changeListener);
        this.model.addActionListener(actionListener);
    }
    updateButton();
}
public void setUI(ButtonUI newUI) {
    if (this.ui != null) this.ui.uninstallUI(this);
    this.ui = newUI;
    if (this.ui != null) this.ui.installUI(this);
    updateButton();
}

架構優勢總結

  1. 關注點分離:業務邏輯、外觀渲染、交互處理三維解耦
  2. 運行時可變:無需重啟即可切換 Look-and-Feel 或行為模式
  3. 組件復用:同一 Model 可配合不同 UI 實現跨平台一致行為
  4. 測試友好:Model 可獨立於 UI 進行單元測試
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved