2019年4月20日 星期六

把既有程式改成 MVC Design Pattern



程式開發久了通常會遇到頁面上的控制項的關聯越來越亂的問題

  • 可能 控制項A 會改狀態列的訊息,控制項B 卻忘了改。
  • 可能 控制項A 改了,值卻沒有存下來。或是按了取消,值卻存下來了。

當頁面上的控制項越多,維護這些關聯就更困難。這時候最適合採用 MVC design pattern。



優點


  • 簡化程式,模組之間並相對獨立,可以抽換。
  • 確保每一個變數修改都會更新介面上每一個控制項。
  • 確保所有控制項被修改,關聯的控制項也都會被修改。
  • 確保控制項的修改都會被存起來。


MVC Design Pattern

將頁面分成模組(Model) - 視圖(View) - 控制器(Controller) 三個部分


Model

  • Model 管理資料還有可以做的行為 (Action)
  • 資料有修改時,通知所有 Event Listener 修改
View
  • 介面設計
  • 有經驗的程式設計師會知道,介面常常會被要求要修改。
Controller
  • 連接鍵盤滑鼠和控制項的 event callback,並修改 Model。
  • 可以方便的修改 Key Mapping,多個控制項做同一件事

範例

以 WinForm C# 為範例,程式長得像這樣


    public partial class Form3 : Form
    {
        //////////////////////////////////////////
        // Model
        public class Models
        {
            public Action<Models> UpdateUI;

            public Models()
            {
            }

            private DateTime _data1;
            public DateTime data1 {
                get
                {
                    return _data1;
                }
                set
                {
                    if (_data1 != value)
                    {
                        _data1 = value;
                        UpdateUI(this);   // 通知 Listener 修改
                    }
                }
            }

            private string _data2;
            public string data2
            {
                get
                {
                    return _data2;
                }
                set
                {
                    if (_data2 != value)
                    {
                        _data2 = value;
                        UpdateUI(this);  // 通知 Listener 修改
                    }
                }
            }
        }

        public Models result;

        public Form3()
        {
            InitializeComponent();
            result = new Models();
            result.UpdateUI = UpdateUI;
        }

        //////////////////////////////////////////
        // View
        private void UpdateUI(Models v)
        { 
            dateTimePicker1.Value = v.data1;
            label1.Text = v.data2;
        }
        
        //////////////////////////////////////////
        // Controller
        private void button1_Click(object sender, EventArgs e)
        {
            result.data1 = DateTime.Now;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            result.data2 = "test";
        }
    }

檢查SOP

發現下面項目有違反時,表示要修改
  • Model 不允許用到任何 Controller 或 View 的 code
  • Controller 區段只能修改 Model,不准用到任何 UI 元件
  • 所有修改 UI 元件的動作都在 UpdateUI() 這個函數內。

沒有留言:

張貼留言