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

建造者模式 C 語言實戰:以 LRC 歌詞解析器為例

     編輯:關於C語言
 

模式意圖與隱喻

建造者模式將複雜對象的構建過程與其表示分離,使相同構建過程可創建不同表示。
經典隱喻:磚廠(構建基本元素)與建築公司(創建最終表示)分離。SAX XML 解析器即典型應用:解析器負責「構建」(產出標籤、文本事件),多種 Builder 負責「創建」(生成 DOM 樹、轉 PDF、提取屬性等)。

核心角色

  • Director (指揮者):掌握構建算法/流程(如 LrcParser),調用 Builder 介面。
  • Builder (抽象建造者):定義構建步驟介面(on_begin, on_id_tag, on_time_tag, on_lrc, on_end, destroy)。
  • ConcreteBuilder (具體建造者):實現介面,產出不同 Product(如 LrcDumpBuilder 輸出文本,LrcDefaultBuilder 構建內存樹)。
  • Product (產品):最終複雜對象(文本輸出或 LrcTree 數據結構)。

LRC 格式與解析邏輯

LRC 由三類元素組成:

  • ID 標籤:[ar:Artist], [ti:Title]
  • 時間標籤:[mm:ss.xx],可多個連續
  • 歌詞文本:時間標籤後的文本行

解析器 LrcParser 以有限狀態機逐行掃描,識別 [ 開頭為標籤,數字開頭為時間標籤,否則為 ID 標籤;普通文本直接回調 on_lrc。

關鍵代碼結構 (精簡)

Builder 介面

typedef struct _LrcBuilder {
    LrcBuilderBegin on_begin;
    LrcBuilderOnIDTag on_id_tag;
    LrcBuilderOnTimeTag on_time_tag;
    LrcBuilderOnLrc on_lrc;
    LrcBuilderEnd on_end;
    LrcBuilderDestroy destroy;
    char priv[1];  // 柔性數組,存具體 Builder 私有數據
} LrcBuilder;

DumpBuilder (調試/美化輸出)

static LRC_RESULT on_time_tag(LrcBuilder* thiz, size_t ms) {
    int min = ms / 60000, sec = (ms % 60000) / 1000, cs = ms % 1000 / 10;
    fprintf(data->fp, "[%d:%02d.%02d]", min, sec, cs);
    return LRC_RESULT_OK;
}
static LRC_RESULT on_lrc(LrcBuilder* thiz, const char* lrc, size_t len) {
    fwrite(lrc, len, 1, data->fp);
    fputc('\n', data->fp);
    return LRC_RESULT_OK;
}

DefaultBuilder (構建內存樹)

static LRC_RESULT on_time_tag(LrcBuilder* thiz, size_t ms) {
    LrcTimeTag* tag = lrc_time_tag_new(pool, ms, NULL);
    lrc_list_insert(&iter, tag, 0);  // 暫存時間標籤
    return LRC_RESULT_OK;
}
static LRC_RESULT on_lrc(LrcBuilder* thiz, const char* lrc, size_t len) {
    char* copy = lrc_strdup(data, lrc, len);
    for each temp_time_tag:
        lrc_time_tag_set_lrc(tag, copy);
        lrc_tree_add_time_tag(tree, tag);
    lrc_list_reset(temp_time_tags);
    return LRC_RESULT_OK;
}

Client 組裝調用

LrcParser* parser = lrc_parser_new_from_file("song.lrc");
LrcBuilder* builder = lrc_default_builder_new();
lrc_parser_run(parser, builder);
LrcTree* tree = lrc_default_builder_get_tree(builder);
builder->destroy(builder);
lrc_parser_destroy(parser);

模式優勢總結

  1. 復用解析邏輯:Parser 不變,擴展新 Builder 即可支持新輸出格式。
  2. 單一職責:解析與表示構建解耦,各自變化互不影響。
  3. 隱藏複雜度:Client 僅需組裝 Parser + Builder,無需關心內部構建細節。

C 語言實現要點

  • 用函數指針結構體模擬介面/多態。
  • 柔性數組 char priv[1] 實現「繼承」與私有數據封裝。
  • 生命周期管理:_new 分配,destroy 釋放,get_product 取結果。

結語

建造者模式在「輸入格式固定、輸出表示多變」場景極具價值。C 語言雖無原生介面,但以函數指針表 + 柔性數組即可優雅實現,SAX/LRC 解析器即最佳證明。

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