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

Java Swing MVC 模式實戰:聯繫人管理系統完整示例

     編輯:Java 程式設計入門

MVC 在 Swing 中的角色劃分

層職責示例類
Model數據狀態、業務邏輯、持久化ContactModel
ViewUI 組件佈局、數據顯示、用戶輸入收集ContactEditView, ContactDisplayView
Controller事件處理、模型更新、視圖同步ContactEditController

核心接口定義


// 模型接口
interface ContactModel {
    void setName(String name);
    String getName();
    void setPhone(String phone);
    String getPhone();
    void setEmail(String email);
    String getEmail();
    void addChangeListener(ChangeListener l);
    void removeChangeListener(ChangeListener l);
}

// 視圖接口
interface ContactView {
    void setModel(ContactModel model);
    void setController(ContactController controller);
    void refresh();  // 從模型同步數據
}

// 控制器接口
interface ContactController {
    void handleNameChange(String newName);
    void handlePhoneChange(String newPhone);
    void handleEmailChange(String newEmail);
}

Model 實現:可觀察的數據模型


class ContactModelImpl implements ContactModel {
    private String name, phone, email;
    private final EventListenerList listeners = new EventListenerList();
    
    // 屬性讀寫 + 觸發事件
    public void setName(String name) {
        if (!Objects.equals(this.name, name)) {
            this.name = name;
            fireChangeEvent();
        }
    }
    
    public String getName() { return name; }
    // phone, email 同理...
    
    // 監聽器管理
    public void addChangeListener(ChangeListener l) {
        listeners.add(ChangeListener.class, l);
    }
    public void removeChangeListener(ChangeListener l) {
        listeners.remove(ChangeListener.class, l);
    }
    
    private void fireChangeEvent() {
        ChangeEvent e = new ChangeEvent(this);
        for (ChangeListener l : listeners.getListeners(ChangeListener.class)) {
            l.stateChanged(e);
        }
    }
}

View 實現:編輯視圖與顯示視圖

編輯視圖(支持交互)


class ContactEditView extends JPanel implements ContactView {
    private JTextField nameField, phoneField, emailField;
    private ContactModel model;
    private ContactController controller;
    
    public ContactEditView() {
        setLayout(new GridLayout(3, 2));
        add(new JLabel("姓名:")); add(nameField = new JTextField());
        add(new JLabel("電話:")); add(phoneField = new JTextField());
        add(new JLabel("郵箱:")); add(emailField = new JTextField());
        
        // 綁定輸入事件 → 控制器
        nameField.getDocument().addDocumentListener(new DocumentListener() {
            public void insertUpdate(DocumentEvent e) { notifyChange(); }
            public void removeUpdate(DocumentEvent e) { notifyChange(); }
            public void changedUpdate(DocumentEvent e) { notifyChange(); }
            void notifyChange() { 
                if (controller != null) controller.handleNameChange(nameField.getText()); 
            }
        });
        // phoneField, emailField 同理...
    }
    
    public void setModel(ContactModel model) {
        this.model = model;
        model.addChangeListener(e -> refresh());
    }
    
    public void setController(ContactController controller) {
        this.controller = controller;
    }
    
    public void refresh() {
        nameField.setText(model.getName());
        phoneField.setText(model.getPhone());
        emailField.setText(model.getEmail());
    }
}

顯示視圖(只讀,自動同步)


class ContactDisplayView extends JPanel implements ContactView {
    private JLabel nameLabel, phoneLabel, emailLabel;
    private ContactModel model;
    
    public ContactDisplayView() {
        setLayout(new GridLayout(3, 2));
        add(new JLabel("姓名:")); add(nameLabel = new JLabel());
        add(new JLabel("電話:")); add(phoneLabel = new JLabel());
        add(new JLabel("郵箱:")); add(emailLabel = new JLabel());
    }
    
    public void setModel(ContactModel model) {
        this.model = model;
        model.addChangeListener(e -> refresh());
    }
    
    public void setController(ContactController c) {}  // 無需控制器
    
    public void refresh() {
        nameLabel.setText(model.getName());
        phoneLabel.setText(model.getPhone());
        emailLabel.setText(model.getEmail());
    }
}

Controller 實現


class ContactEditController implements ContactController {
    private ContactModel model;
    
    public ContactEditController(ContactModel model) {
        this.model = model;
    }
    
    public void handleNameChange(String name) {
        model.setName(name);  // 觸發事件 → 所有視圖自動 refresh()
    }
    
    public void handlePhoneChange(String phone) {
        model.setPhone(phone);
    }
    
    public void handleEmailChange(String email) {
        model.setEmail(email);
    }
}

主程序裝配


public class RunMVCPattern {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            // 1. 創建共享模型
            ContactModel model = new ContactModelImpl();
            
            // 2. 創建視圖
            ContactView editView = new ContactEditView();
            ContactView displayView = new ContactDisplayView();
            
            // 3. 創建控制器
            ContactController controller = new ContactEditController(model);
            
            // 4. 綁定關係
            editView.setModel(model);
            editView.setController(controller);
            displayView.setModel(model);  // 共享同一模型
            
            // 5. 構建窗口
            JFrame editFrame = new JFrame("聯繫人編輯");
            editFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            editFrame.add(editView);
            editFrame.pack();
            editFrame.setLocation(100, 100);
            editFrame.setVisible(true);
            
            JFrame displayFrame = new JFrame("聯繫人顯示(同步更新)");
            displayFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            displayFrame.add(displayView);
            displayFrame.pack();
            displayFrame.setLocation(500, 100);
            displayFrame.setVisible(true);
        });
    }
}

MVC 優勢演示

  • 單一模型,多視圖:編輯窗口修改 → 顯示窗口自動同步
  • 視圖可替換:無需修改模型/控制器,可接入 Web/手機端視圖
  • 邏輯可測試:Controller/Model 可獨立單元測試,無需啟動 UI
  • 職責分離:UI 代碼不混雜業務邏輯

現代化改進方向

  • 使用 PropertyChangeSupport 替換手動監聽器
  • 引入 SwingWorker 處理異步數據加載
  • 考慮 JavaFX + MVVM (FXML + ViewModel) 替代 Swing MVC
  • 數據綁定框架:JGoodies Binding、Griffon

這個示例展示了 MVC 在桌面應用中的經典應用:模型發射事件,視圖訂閱事件,控制器轉發命令,實現了關注點清晰分離。

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