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

C# 設計模式實戰:State 狀態模式完整解析(一)

     編輯:關於C語言

模式意圖

允許物件在內部狀態改變時改變行為,物件彷彿修改了它的類別。

應用場景:網路書店會員等級系統

用戶消費達標升級:普通 → 銀 → 金 → 鑽,不同等級享不同折扣。若在 User.BuyBook 內用 if-else 判斷等級計算折扣,問題三點:

  1. 折扣率常變 → 修改 User 類別
  2. 新增等級(鑽石、白金) → 修改 User 類別
  3. User 承擔等級判斷、折扣計算等複雜邏輯 → 維護困難

引入 State 模式,分離物件與狀態,將狀態轉換與行為委派給具體狀態類別。

完整實作代碼


using System;
using System.Collections.Generic;
using System.Text;

namespace StateExample
{
    class Program
    {
        static void Main(string[] args)
        {
            User user = new User("zhuye");
            user.BuyBook(2000);
            user.BuyBook(2000);
            user.BuyBook(2000);
            user.BuyBook(2000);
        }
    }

    class User // Context
    {
        private UserLevel _userLevel;
        public UserLevel UserLevel { get { return _userLevel; } set { _userLevel = value; } }

        private string _userName;
        private double _paidMoney;
        public double PaidMoney { get { return _paidMoney; } }

        public User(string userName)
        {
            _userName = userName;
            _paidMoney = 0;
            _userLevel = new NormalUser(this);
        }

        public void BuyBook(double amount)
        {
            Console.WriteLine($"Hello {_userName}, You have paid ${_paidMoney}, You Level is {_userLevel.GetType().Name}.");
            double realAmount = _userLevel.CalcRealAmount(amount);
            Console.WriteLine("You only paid $" + realAmount + " for this book.");
            _paidMoney += realAmount;
            _userLevel.StateCheck();
        }
    }

    abstract class UserLevel // State
    {
        protected User _user;
        public UserLevel(User user) { _user = user; }
        public abstract void StateCheck();
        public abstract double CalcRealAmount(double amount);
    }

    class DiamondUser : UserLevel
    {
        public DiamondUser(User user) : base(user) { }
        public override double CalcRealAmount(double amount) => amount * 0.7;
        public override void StateCheck() { } // 最高級無轉換
    }

    class GoldUser : UserLevel
    {
        public GoldUser(User user) : base(user) { }
        public override double CalcRealAmount(double amount) => amount * 0.8;
        public override void StateCheck()
        {
            if (_user.PaidMoney > 5000) _user.UserLevel = new DiamondUser(_user);
        }
    }

    class SilverUser : UserLevel
    {
        public SilverUser(User user) : base(user) { }
        public override double CalcRealAmount(double amount) => amount * 0.9;
        public override void StateCheck()
        {
            if (_user.PaidMoney > 2000) _user.UserLevel = new GoldUser(_user);
        }
    }

    class NormalUser : UserLevel
    {
        public NormalUser(User user) : base(user) { }
        public override double CalcRealAmount(double amount) => amount * 0.95;
        public override void StateCheck()
        {
            if (_user.PaidMoney > 1000) _user.UserLevel = new SilverUser(_user);
        }
    }
}

關鍵設計亮點

  • 狀態轉換邏輯分散在各狀態類別,User 完全不知曉具體轉換規則
  • 新增等級只需新增 State 類別 + 修改前一級的 StateCheck
  • 折扣計算封裝在各狀態,互不干擾
  • Context (User) 僅負責協調:顯示資訊 → 委派計算 → 累計金額 → 觸發檢查

狀態轉換圖

NormalUser (95%) --> SilverUser (90%) --> GoldUser (80%) --> DiamondUser (70%)
     ↑ 1000             ↑ 2000              ↑ 5000              (終態)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved