iT邦幫忙

2026 iThome 鐵人賽

DAY 3
0
Software Development

下載器不是寫完就能跑:一個 HLS 分段式串流工具的架構與測試修練系列 第 3

Day 03:用 Factory 依網址判斷該用哪個爬蟲,而不是到處寫 if-else

  • 分享至 

  • xImage
  •  

前言:呼叫端要知道「這個網址該用哪個爬蟲」嗎?

「呼叫端傳個網址進來,判斷一下網域是哪個站台,new 對應的爬蟲就好了吧?」

問題是:這個判斷邏輯只寫一次,很快就會被複製到第二個、第三個呼叫端。今天新增一個來源站,就要回頭把每一處判斷邏輯都加上一個 elif——而且很容易漏掉某一處。

今日目標

  • 認識「該用哪個實作」這個決策本身也該被封裝成一個獨立單元
  • 看一組「呼叫端自己判斷 vs Factory 集中判斷」的對照
  • 知道 Factory Pattern 解決的不是「怎麼判斷」,而是「判斷邏輯該放哪」

❌ vs ✅:判斷邏輯散落 vs 集中在一個地方

❌ 反例:每個呼叫端各自判斷

def process(url):
    domain = urlparse(url).netloc
    if 'site-b' in domain:
        crawler = SiteB()
    else:
        crawler = SiteA()
    ...

def another_process(url):
    domain = urlparse(url).netloc
    if 'site-b' in domain:  # 同樣的判斷又寫一次
        crawler = SiteB()
    else:
        crawler = SiteA()
    ...

✅ 正例:Factory 集中負責「該用哪個」

class CrawlerFactory:
    def create(self, url: str) -> Crawler:
        domain = urlparse(url).netloc
        if 'site-b' in domain:
            return SiteB()
        return SiteA()

def process(url, factory: CrawlerFactory):
    crawler = factory.create(url)
    ...

新增一個來源站時,只要改 CrawlerFactory.create() 這一個地方,所有呼叫端不用動一行程式碼。

嚴格來說,這裡示範的是集中判斷邏輯的 Simple Factory 寫法(一個方法裡用條件判斷回傳不同類別),跟 GoF 定義的 Factory Method(由子類別各自透過多型決定要建立哪個物件,而不是集中在一處 if-else)並不是同一個模式。業界口語上很常把兩者都泛稱「Factory Pattern」,這裡沿用這個習慣說法,但值得知道兩者的差異,對照 GoF 原典時才不會搞混。

這個判斷邏輯本身也該被測試

「該用哪個爬蟲」聽起來像是個瑣碎的 if-else,但它是一個有明確輸入輸出、值得獨立驗證的邏輯單元:給定一個網址,應該回傳哪個類別的實例。集中成一個 Factory 之後,測試也集中成一份——不用在每個呼叫端各自驗證一次判斷邏輯對不對。

今日思考題

你的專案裡有沒有「該用哪個實作」這種判斷散落在多個呼叫端的情況?如果現在要新增一種情境,你要改幾個地方?

今日重點回顧

  • 「該用哪個實作」是一個獨立的決策單元,值得封裝成自己的類別
  • Factory 讓新增情境時,呼叫端完全不用改動
  • 集中的判斷邏輯,測試也可以集中驗證,不用每個呼叫端各自驗證一次

明日預告

明天進入一個真實踩過的坑:從頁面裡取出 M3U8 位置時,那段資料被包在一段字串化的 JSON 裡,用正規表達式硬解析容易在哪裡出包。


上一篇
Day 02:每個來源站的頁面結構都不一樣,抽象層要切在哪裡
下一篇
Day 04:案例——字串裡包一段 JSON 的 M3U8 連結,怎麼解析比較不脆弱
系列文
下載器不是寫完就能跑:一個 HLS 分段式串流工具的架構與測試修練4
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言