iT邦幫忙

2025 iThome 鐵人賽

DAY 7
0

昨天我們初步認識了 OOP 三大特性。今天進一步,看看繼承的應用,並帶入 介面 (Interface)DI/IoC 的設計思維。


繼承 (Inheritance)

繼承的好處是 重用程式碼,不用每次都重寫相同的屬性或方法。

/// <summary>
/// 股票基本資訊
/// </summary>
public class Stock
{
    public string Symbol { get; set; }
    public decimal Price { get; set; }
}

/// <summary>
/// 股票檔案:繼承 Stock 並擴充產業別
/// </summary>
public class StockProfile : Stock
{
    public string Industry { get; set; }
}

👉 StockProfile 自動擁有 SymbolPrice,額外加上 Industry


介面 (Interface)

介面 是一種「契約」,定義規則,誰實作誰遵守。

/// <summary>
/// 選股策略介面
/// </summary>
public interface IStockStrategy
{
    bool Match(Stock stock);
}

👉 不管策略內容是 MACD、KD 或基本面分析,都必須提供一個 Match 方法。


實戰:MACD 與 KD 策略

我們來定義兩個策略:

MACD OSC 往上大於 0

/// <summary>
/// MACD OSC > 0 則符合
/// </summary>
public class MacdOscStrategy : IStockStrategy
{
    public bool Match(Stock stock)
    {
        // 假設這裡從技術分析模組取出 OSC 值
        decimal osc = GetMacdOsc(stock.Symbol);

        return osc > 0;
    }

    private decimal GetMacdOsc(string symbol)
    {
        // 簡化:真實情況要用技術指標計算
        return 1.23m;
    }
}

KD 黃金交叉

/// <summary>
/// KD 黃金交叉 (K 值突破 D 值) 則符合
/// </summary>
public class KdGoldenCrossStrategy : IStockStrategy
{
    public bool Match(Stock stock)
    {
        (decimal k, decimal d) = GetKdValues(stock.Symbol);

        return k > d; // K 線往上突破 D 線
    }

    private (decimal k, decimal d) GetKdValues(string symbol)
    {
        // 簡化:真實情況要透過歷史資料計算
        return (75m, 70m);
    }
}

使用:

Stock s1 = new Stock { Symbol = "2330", Price = 1265m };

IStockStrategy macd = new MacdOscStrategy();
IStockStrategy kd = new KdGoldenCrossStrategy();

Console.WriteLine(macd.Match(s1)); // true
Console.WriteLine(kd.Match(s1));   // true

👉 好處:策略互相獨立,但都能共用同一個介面。



學習第一個設計模式-DI/IoC

什麼是 DI (依賴注入)?

假設我們的 StockService 要用到一個「選股策略」。
傳統的寫法是:

  • 程式自己決定要用哪個策略(自己 new)。

沒有 DI

public class StockService
{
    private readonly IStockStrategy _strategy = new MacdOscStrategy(); // 直接 new

    public bool IsMatch(Stock stock)
    {
        return _strategy.Match(stock);
    }
}

👉 問題:

  • StockService 被「綁死」在 MacdOscStrategy
  • 想換成 KD 策略就要改 StockService 的程式碼。

有了 DI

public class StockService
{
    private readonly IStockStrategy _strategy;

    public StockService(IStockStrategy strategy) // 由外部注入
    {
        _strategy = strategy;
    }

    public bool IsMatch(Stock stock)
    {
        return _strategy.Match(stock);
    }
}

👉 好處

  • 想換策略,只要在外部傳不同物件進去。
  • 更容易做單元測試,可以傳入 MockStrategy

這就是 DI (依賴注入)
把物件的「依賴」交給外部注入,而不是自己 new

IoC 的概念是:

  • 把控制權交給外部(例如 DI 容器或框架),由它來決定注入哪個物件。

  • 👉 簡單來說:

  • IoC 是「控制權反轉」的設計理念。

  • DI 是 IoC 的其中一種具體做法。


為什麼要用 DI/IoC?

如果我們直接在程式裡 new 策略,會發生:

public class StockService
{
    private readonly IStockStrategy _strategy = new MacdOscStrategy(); // 綁死
}

👉 問題:

  • 想換成 KD 策略,程式碼要修改。
  • 測試時很難替換假資料。

解法:DI (Dependency Injection)

public class StockService
{
    private readonly IStockStrategy _strategy;

    public StockService(IStockStrategy strategy) // 注入策略
    {
        _strategy = strategy;
    }

    public bool IsMatch(Stock stock)
    {
        return _strategy.Match(stock);
    }
}

使用:

Stock s1 = new Stock { Symbol = "2330", Price = 1265m };

// 換策略只要換注入的物件
StockService service1 = new StockService(new MacdOscStrategy());
StockService service2 = new StockService(new KdGoldenCrossStrategy());

Console.WriteLine(service1.IsMatch(s1)); // true
Console.WriteLine(service2.IsMatch(s1)); // true

👉 好處

  • 策略可自由替換。
  • 更容易測試(可以注入 MockStrategy)。
  • 這就是 IoC(控制反轉):程式不再「控制要用誰」,而是「外部告訴它要用誰」。

小結

今天我們學會了:

  • 繼承:在 StockProfile 基礎上擴充產業別。
  • 介面:定義選股策略的共通規則。
  • 策略實戰:MacdOscStrategyKdGoldenCrossStrategy
  • DI/IoC:讓程式更彈性、易測試、低耦合。

上一篇
Day 6 - 物件導向程式設計 (OOP) 入門
下一篇
Day 8 - 集合 (List, Dictionary) 與股票清單管理
系列文
30天快速上手製作WPF選股工具 — 從C#基礎到LiteDB與Web API整合11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言