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

C# 實戰 MVC 模式:從汽車儀表盤到靈活擴展的架構設計

     編輯:關於C語言

前言:為什麼選擇 MVC?

在開發項目中採用 MVC (Model-View-Controller) 模式,核心收益在於徹底解耦業務邏輯層與表示層。擁有完全獨立的對象操作 UI,使維護更簡單、代碼復用極易。遵循「面向接口編程,而非面向實現編程」原則,將依賴降至最低,讓系統輕鬆應對需求變更。

案例背景:ACME 車輛控制系統

構建一個 Windows 界面顯示汽車方向與速度,用戶可改變方向、加速、減速。未來需擴展支持皮卡、三輪車,甚至移植到 Intranet Web 界面。這正是 MVC 大顯身手的完美場景。

架構設計:三大核心角色

  • Model (汽車):封裝車輛狀態 (速度、方向、最大限制) 及行為 (加速、減速、轉向)
  • View (儀表盤界面):顯示車輛狀態,暴露 UI 控制啟用/禁用方法
  • Controller (控制器):協調 Model 與 View,處理用戶請求,執行業務規則驗證 (如超速禁止轉向)

交互流程:用戶操作 View → View 委託 Controller → Controller 操作 Model 並更新 View → Model 狀態變更通知 View (觀察者模式) → View 刷新顯示。

核心接口定義 (面向接口編程)

1. 方向枚舉

public enum AbsoluteDirection { North = 0, East, South, West }
public enum RelativeDirection { Right, Left, Back }

2. Controller 接口

public interface IVehicleControl
{
    void RequestAccelerate(int amount);
    void RequestDecelerate(int amount);
    void RequestTurn(RelativeDirection direction);
    void SetModel(IVehicleModel model);
    void SetView(IVehicleView view);
}

3. Model 接口 (含觀察者模式)

public interface IVehicleModel
{
    string Name { get; set; }
    int Speed { get; set; }
    int MaxSpeed { get; }
    int MaxTurnSpeed { get; }
    int MaxReverseSpeed { get; }
    AbsoluteDirection Direction { get; set; }
    
    void Accelerate(int amount);
    void Decelerate(int amount);
    void Turn(RelativeDirection direction);
    
    // 觀察者模式:Model 通知 View 狀態變更
    void AddObserver(IVehicleView view);
    void RemoveObserver(IVehicleView view);
    void NotifyObservers();
}

4. View 接口

public interface IVehicleView
{
    void DisableAcceleration(); void EnableAcceleration();
    void DisableDeceleration(); void EnableDeceleration();
    void DisableTurning(); void EnableTurning();
    void Update(IVehicleModel model); // 觀察者回調
}

基礎實現:Automobile 抽象類 (Model 骨架)

public abstract class Automobile : IVehicleModel
{
    private readonly ArrayList _observers = new ArrayList();
    private int _speed;
    private readonly int _maxSpeed, _maxTurnSpeed, _maxReverseSpeed;
    private AbsoluteDirection _direction = AbsoluteDirection.North;
    private string _name;

    protected Automobile(int maxSpeed, int maxTurnSpeed, int maxReverseSpeed, string name)
    {
        _maxSpeed = maxSpeed;
        _maxTurnSpeed = maxTurnSpeed;
        _maxReverseSpeed = maxReverseSpeed;
        _name = name;
    }

    // 觀察者模式實現
    public void AddObserver(IVehicleView view) => _observers.Add(view);
    public void RemoveObserver(IVehicleView view) => _observers.Remove(view);
    public void NotifyObservers()
    {
        foreach (IVehicleView view in _observers)
            view.Update(this);
    }

    // 屬性實現
    public string Name { get => _name; set => _name = value; }
    public int Speed => _speed;
    public int MaxSpeed => _maxSpeed;
    public int MaxTurnSpeed => _maxTurnSpeed;
    public int MaxReverseSpeed => _maxReverseSpeed;
    public AbsoluteDirection Direction => _direction;

    // 行為實現 (狀態變更後通知觀察者)
    public void Turn(RelativeDirection dir)
    {
        _direction = dir switch
        {
            RelativeDirection.Right => (AbsoluteDirection)((int)(_direction + 1) % 4),
            RelativeDirection.Left => (AbsoluteDirection)((int)(_direction + 3) % 4),
            RelativeDirection.Back => (AbsoluteDirection)((int)(_direction + 2) % 4),
            _ => AbsoluteDirection.North
        };
        NotifyObservers();
    }

    public void Accelerate(int amount)
    {
        _speed += amount;
        if (_speed > _maxSpeed) _speed = _maxSpeed;
        NotifyObservers();
    }

    public void Decelerate(int amount)
    {
        _speed -= amount;
        if (_speed < _maxReverseSpeed) _speed = _maxReverseSpeed;
        NotifyObservers();
    }
}

具體車輛實現

// 運動車
public class ACME2000SportsCar : Automobile
{
    public ACME2000SportsCar(string name) : base(250, 40, -20, name) { }
    public ACME2000SportsCar(string name, int maxSpeed, int maxTurn, int maxRev) 
        : base(maxSpeed, maxTurn, maxRev, name) { }
}

// 貨車 - 僅需新增此類,零修改現有代碼
public class ACME2000Truck : Automobile
{
    public ACME2000Truck(string name) : base(80, 25, -12, name) { }
}

Controller 實現:業務規則封裝

public class AutomobileControl : IVehicleControl
{
    private IVehicleModel _model;
    private IVehicleView _view;

    public AutomobileControl() { }
    public AutomobileControl(IVehicleModel model, IVehicleView view)
    {
        SetModel(model); SetView(view);
    }

    public void SetModel(IVehicleModel model) => _model = model;
    public void SetView(IVehicleView view) => _view = view;

    public void RequestAccelerate(int amount)
    {
        _model?.Accelerate(amount);
        UpdateViewState();
    }
    public void RequestDecelerate(int amount)
    {
        _model?.Decelerate(amount);
        UpdateViewState();
    }
    public void RequestTurn(RelativeDirection dir)
    {
        _model?.Turn(dir);
        UpdateViewState();
    }

    // 核心業務邏輯:根據 Model 狀態控制 View 可用性
    private void UpdateViewState()
    {
        if (_view == null) return;

        if (_model.Speed >= _model.MaxSpeed)
        { _view.DisableAcceleration(); _view.EnableDeceleration(); }
        else if (_model.Speed <= _model.MaxReverseSpeed)
        { _view.DisableDeceleration(); _view.EnableAcceleration(); }
        else
        { _view.EnableAcceleration(); _view.EnableDeceleration(); }

        if (_model.Speed >= _model.MaxTurnSpeed)
            _view.DisableTurning();
        else
            _view.EnableTurning();
    }
}

View 實現:WinForms UserControl

public class AutoView : UserControl, IVehicleView
{
    private IVehicleControl _control = new AutomobileControl();
    private IVehicleModel _model = new ACME2000SportsCar("Speedy");
    
    // UI 元素: btnAccelerate, btnDecelerate, btnLeft, btnRight, lblStatus, pBar...

    public AutoView()
    {
        InitializeComponent();
        WireUp(_control, _model);
    }

    public void WireUp(IVehicleControl control, IVehicleModel model)
    {
        // 解除舊綁定
        if (_model != null) _model.RemoveObserver(this);
        
        _model = model;
        _control = control;
        _control.SetModel(_model);
        _control.SetView(this);
        _model.AddObserver(this);
    }

    // 按鈕事件 -> 委託 Controller
    private void btnAccelerate_Click(object sender, EventArgs e)
        => _control.RequestAccelerate(int.Parse(txtAmount.Text));
    private void btnDecelerate_Click(object sender, EventArgs e)
        => _control.RequestDecelerate(int.Parse(txtAmount.Text));
    private void btnLeft_Click(object sender, EventArgs e)
        => _control.RequestTurn(RelativeDirection.Left);
    private void btnRight_Click(object sender, EventArgs e)
        => _control.RequestTurn(RelativeDirection.Right);

    // 觀察者回調 -> 更新 UI
    public void Update(IVehicleModel model) => UpdateInterface(model);
    
    private void UpdateInterface(IVehicleModel auto)
    {
        lblStatus.Text = $"{auto.Name} heading {auto.Direction} at speed: {auto.Speed}";
        pBar.Value = auto.Speed > 0 
            ? auto.Speed * 100 / auto.MaxSpeed 
            : auto.Speed * 100 / auto.MaxReverseSpeed;
    }

    // IVehicleView 界面控制實現
    public void DisableAcceleration() => btnAccelerate.Enabled = false;
    public void EnableAcceleration() => btnAccelerate.Enabled = true;
    public void DisableDeceleration() => btnDecelerate.Enabled = false;
    public void EnableDeceleration() => btnDecelerate.Enabled = true;
    public void DisableTurning() => btnLeft.Enabled = btnRight.Enabled = false;
    public void EnableTurning() => btnLeft.Enabled = btnRight.Enabled = true;
}

擴展演示:零修改現有代碼添加新功能

1. 新增車輛類型 (皮卡)

// 僅新增類,AutoView 中一行代碼切換
private void btnBuildTruck_Click(object sender, EventArgs e)
{
    autoView1.WireUp(new AutomobileControl(), new ACME2000Truck(txtName.Text));
}

2. 新增控制策略 (限速 5mph/次)

public class SlowPokeControl : IVehicleControl
{
    // ... 實現接口,RequestAccelerate/Decelerate 中限制 amount <= 5
}

// 使用新策略
autoView1.WireUp(new SlowPokeControl(), new ACME2000Truck("Slow Truck"));

3. 移植到 Web 界面

僅需創建實現 IVehicleView 的 Web UserControl (ASP.NET / Blazor / Razor Pages),核心 Model、Controller 零修改復用。

總結

MVC 模式通過接口隔離、觀察者模式解耦狀態通知、依賴注入式裝配,實現了極低耦合、高內聚的架構。本例展示了如何輕鬆應對:新增實體類型、替換控制策略、跨平台 UI 移植。下次項目啟動時,請記住 MVC —— 你不會後悔!

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