承接上一篇的理論基礎,本文透過一個「小書店業務系統」的完整實作,示範如何靈活運用抽象類別與介面,將複雜的業務規則轉化為清晰、可擴充的物件模型。

namespace EBook
{
public enum U_Type { Member, Shopper } // 客戶類型
public enum B_Type { Novel, Life, Magazine } // 書類型
public enum S_Type { Sell, Hire } // 交易類型:銷售/租賃
public enum H_Type { Rent, Back } // 租借動作:租出/歸還
}
Money — 定義契約public interface Money
{
double GetMoney(); // 計算實收/退還金額
string Execute(); // 執行持久化或回傳明細
}
Root — 共享欄位與 Template Method
public abstract class Root : Money
{
protected U_Type _utype; // 客戶類型
protected B_Type _btype; // 書類型
protected S_Type _stype; // 交易類型
protected string _bookname; // 書名
protected string _uname; // 客戶名
protected double _price; // 定價
protected double _cash; // 實收現金
public abstract double GetMoney();
public abstract string Execute();
// Template Method:延遲到具體子類實作
public virtual double TGetMoney() => 0;
public virtual string TExecute() => "";
}
Sell(銷售)與 Hire(租賃)分別繼承 Root,補充各自欄位(如租賃天數、押金),並覆寫 Template Method。
| 類別 | 業務 | 關鍵邏輯 |
|---|---|---|
Buy | 會員購書 | 小說 5 折、生活 8 折、其他原價 |
SBuy | 一般顧客購書 | 小說 6 折、生活 9 折、其他原價 |
Rent | 租書(收押金) | 實收 = 押金(定價),不收租金 |
M_Back | 會員還書 | 退押金 - 會員租金(小說 0.1/天、生活 0.5/天、雜誌 0.1/天) |
S_Back | 一般顧客還書 | 退押金 - 一般租金(小說 0.5/天、生活 1.0/天、雜誌 0.3/天) |
範例:M_Back 會員還書邏輯
public class M_Back : Hire
{
public M_Back(string un, string bn, int day, B_Type bt)
{
_uname = un; _bookname = bn; _day = day; _btype = bt;
}
public override double TGetMoney() => _deposit - GetRent(); // 應找零
private double GetRent()
{
switch (_btype)
{
case B_Type.Novel: _cash = _day * 0.1; break;
case B_Type.Life: _cash = _day * 0.5; break;
case B_Type.Magazine: _cash = _day * 0.1; break;
}
return _cash;
}
public override string TExecute()
=> $"尊敬的顧客,您租借《{_bookname}》,共計:{_day}天,已支付押金{_deposit},實際產生租金{GetRent()}元,應找您{TGetMoney()}元";
}
Factory — 封裝物件建立邏輯
public class Factory
{
private readonly U_Type _utype; private readonly B_Type _btype;
private readonly S_Type _stype; private readonly string _bookname, _uname;
private readonly double _price; private int _day; private H_Type _htype;
public Factory(U_Type ut, B_Type bt, S_Type st, string bn, string un, double p)
{ _utype=ut; _btype=bt; _stype=st; _bookname=bn; _uname=un; _price=p; }
public H_Type Htype { get => _htype; set => _htype = value; }
public int Day { get => _day; set => _day = value; }
public Root HorS() => _stype == S_Type.Hire ? GetHire() : GetBuy();
private Sell GetBuy() => _utype == U_Type.Member
? new Buy(_btype, _uname, _bookname, _price)
: new SBuy(_btype, _uname, _bookname, _price);
private Hire GetHire() => _htype == H_Type.Rent
? new Rent(_uname, _bookname, _price)
: _utype == U_Type.Member
? new M_Back(_uname, _bookname, _day, _btype)
: new S_Back(_uname, _bookname, _day, _btype);
}
// 會員購買小說
var factory = new Factory(U_Type.Member, B_Type.Novel, S_Type.Sell, "C# 進階", "Tom", 300);
Root order = factory.HorS();
double pay = order.GetMoney(); // 150
string msg = order.Execute(); // 取得明細訊息
// 一般顧客租書 3 天
factory = new Factory(U_Type.Shopper, B_Type.Life, S_Type.Hire, "健康飲食", "Mary", 200);
factory.Htype = H_Type.Rent;
order = factory.HorS();
pay = order.GetMoney(); // 200 (押金)
msg = order.Execute();
// 會員歸還
factory.Htype = H_Type.Back; factory.Day = 3;
order = factory.HorS();
pay = order.GetMoney(); // 押金 - 租金
msg = order.Execute();
Money 統一「算錢」與「執行」行為,前端零依賴具體類別。Root 集中共用欄位;Sell/Hire 分流業務維度。GetMoney 呼叫 TGetMoney),子類填充細節。Factory,外部單一入口。完整程式碼已整理於附件,歡迎下載研習。