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

基於 Eclipse SWT 定制組件實現 MVC 架構實戰

     編輯:Java 相關知識

MVC 在豐富客戶端(RCP)的特殊形態

Web MVC 中程序員需手工構建三層,而 Eclipse RCP 通過 JFace Viewer 框架內建了大量控制/呈現邏輯。開發者核心任務是實現業務模型與視圖組件的綁定適配,而非從零構建 MVC。

JFace Viewer 框架:MVC 的標準實現

核心角色映射

MVC 概念JFace 實現職責
ModelContentProvider + 領域對象提供結構化數據、監聽模型變更
ViewViewer (TreeViewer/TableViewer) + SWT Widgets渲染 UI、處理選擇/過濾/排序
ControllerViewPart + LabelProvider + 監聽器協調模型與視圖、處理用戶交互

標準創建流程

public class ExampleView extends ViewPart {
    private TreeViewer viewer;

    public void createPartControl(Composite parent) {
        // 1. 佈局
        GridLayout layout = new GridLayout();
        parent.setLayout(layout);

        // 2. 實例化 Viewer(視圖容器)
        viewer = new TreeViewer(parent, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);

        // 3. 設置提供者(模型適配層)
        viewer.setContentProvider(new ExampleViewContentProvider());
        viewer.setLabelProvider(new ExampleViewLabelProvider());
        viewer.setSorter(new ViewerSorter());

        // 4. 輸入模型根對象
        viewer.setInput(ModelManager.getExampleModel());

        // 5. 註冊選擇提供者,讓動作響應選擇
        getSite().setSelectionProvider(viewer);
        
        hookContextMenu(); // 上下文菜單
    }
}

ContentProvider:模型到視圖的結構適配

接口選擇指南

  • IStructuredContentProvider:列表/表格型視圖,getElements(input) 返回扁平集合
  • ITreeContentProvider:樹型視圖,需實現:
    • getElements(Object input):根節點
    • getChildren(Object parent):子節點
    • getParent(Object child):父節點(可選)
    • hasChildren(Object element):是否有子節點

多視圖共享模型:inputChanged 機制


public class ExampleViewContentProvider implements ITreeContentProvider {
    private Viewer viewer;
    private ExampleDelegate model;

    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
        if (newInput != null) {
            this.viewer = viewer;
            this.model = (ExampleDelegate) newInput;
            this.model.addModelListener(this); // 監聽模型變更,刷新視圖
        }
    }
    // ... getElements/getChildren 實現
}

Viewer 每次 setInput() 都會調用 inputChanged(),實現一模型多視圖同步。

定制表單編輯器:Field 抽象層實現雙向綁定

架構分層


// 抽象字段基類
public abstract class Field {
    protected Control _control;
    protected int _id;
    
    public Field(Control control, int id) { this._control = control; this._id = id; }
    
    // 從模型讀取 → UI
    public abstract void readFromContent(IExampleContentProvider content);
    
    // 從 UI 寫回 → 模型
    public abstract void writeToContent(IExampleContentProvider content);
}

// 文本字段實現
public class TextField extends Field {
    public TextField(Control control, int id) { super(control, id); }
    
    public void readFromContent(IExampleContentProvider content) {
        String text = (String) content.getElement(getId());
        if (text != null) ((Text)_control).setText(text);
    }
    
    public void writeToContent(IExampleContentProvider content) {
        content.setElement(getId(), ((Text)_control).getText());
    }
}

// Combo/Checkbox 等同理擴展

工廠模式創建字段


public class TextFactory {
    public static Control create(Composite parent, int style, GridData gd, FieldMode mode) {
        Text text = new Text(parent, style);
        text.setLayoutData(gd);
        return text;
    }
}
// Layout 類中調用
Control control = TextFactory.create(this, SWT.BORDER, gridData, FieldMode.Edit);
addField(new TextField(control, ExampleViewContentProvider.FIRST_INDEX));

表單初始化與數據同步


public class Form extends Composite {
    private IExampleContentProvider _content;
    
    public Form(Composite parent, int style, FieldMode mode, IExampleContentProvider content) {
        super(parent, style);
        _content = content;
        setMode(mode);
        init(style);
    }
    
    private void init(int style) {
        createControls(style);
        controlsCreated(); // 關鍵鉤子
    }
    
    protected void controlsCreated() {
        readFromContent(); // 遍歷所有字段調用 readFromContent()
    }
    
    private void readFromContent() {
        for (Field field : fields) {
            field.readFromContent(_content);
        }
    }
    
    public void save() {
        for (Field field : fields) {
            field.writeToContent(_content); // 提交時寫回模型
        }
    }
}

簡化模型實現:基於 ID 的數據訪問


public class ExampleViewContentProvider implements IExampleContentProvider {
    public static final int FIRST_INDEX = 0;   // Email
    public static final int SECOND_INDEX = 1;  // Group
    // ...
    
    public Object getElement(int index) {
        switch (index) {
            case FIRST_INDEX:  return "developer@ibm.com";
            case SECOND_INDEX: return new Integer(1);
            case THIRD_INDEX:  return Boolean.FALSE;
            // ...
        }
        return null;
    }
    
    public void setElement(int index, Object value) {
        // 實際項目中持久化到 XML/數據庫
        // 並通知監聽器模型已變更
    }
}

關鍵設計模式總結

  1. Viewer 作為視圖容器:封裝 SWT Widget,提供選擇/過濾/排序等 UI 邏輯
  2. ContentProvider 作為模型適配器:將領域模型轉為 Viewer 可識別的結構化數據
  3. LabelProvider 作為顯示適配器:將模型元素轉為文本/圖標
  4. Field 抽象層解耦 UI 控件:統一 readFromContent/writeToContent 協議,支援任意控件類型
  5. 工廠模式創建控件:Layout 類不直接依賴具體 Widget 類
  6. inputChanged 實現模型多視圖同步:JFace 框架自動調用,開發者只需註冊監聽器

結語

Eclipse RCP 的 MVC 實踐核心在於利用框架內建的 Controller/View 基礎設施,開發者專注於 ContentProvider/LabelProvider/Field 三個適配層的實現。這種「約定優於配置」的設計,配合 SWT/JFace 豐富的 Widget 庫,能以極低複雜度構建企業級富客戶端應用。

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