Fluent Builder 模式

前言

以前最討厭設計複雜方法調用, 就是那種需要一堆有邏輯規則的 config 作爲參數的方法. 

這種 config 通常是一個大對象, 有許多 property, property 之間有存在一些邏輯, 比如當 property A 是什麼的時候 B 必須也是什麼.

如果單側不管它, 那麼調用方法的人就會很幸苦, 一直到 runtime 纔會報錯.

 

Fluent Builder 模式

Fluent Builder 模式就是用來有條有理的創建複雜對象的. 比如上面說到的 config.

很多地方都可以看到它的影子.

EF Core 和 OData 都用了這個方式來創建 model.

fluentvalidation 也是用了這個方式來創建 validation rules

 

如何實現

參考: Fluent Builder模式簡介

其內部原理就是通過幾個小的 builder, 每一個 builder 負責一部分創建. 然後串起來.

每一個小 builder 就可以通過方法, 去聲明類型, 和限制調用順序等.

雖然它不能 100% 解決使用者調用錯誤的問題, 但是已經非常多了. 

在設計方法調用的時候, 我們不可以認爲使用者是開發人員就順便的做, 應該要儘可能讓調用簡單, 智能, 有類型推到.

before 

builder.HasPrincipalProperty(e => e.ProductName, e => e.Color.Product.Name, conditionalInfo: new RedundancyExpressionVersionConditionalInfo<Size>
{
    WhereExpression = e => e.Type == SizeType.TypeA,
    WhenNoInCondition = WhenNoInCondition.AutomaticallySetToNull
});
builder.HasPrincipalProperty(e => e.ProductId, e => e.Color.Product.Id, conditionalInfo: new RedundancyExpressionVersionConditionalInfo<Size>
{
    WhereExpression = e => e.Type == SizeType.TypeA,
    WhenNoInCondition = WhenNoInCondition.AutomaticallySetToNull
});
builder.HasPrincipalProperty(e => e.Age, e => e.Color.Product.Age, conditionalInfo: new RedundancyExpressionVersionConditionalInfo<Size>
{
    WhereExpression = e => e.Type == SizeType.TypeA,
    WhenNoInCondition = WhenNoInCondition.AutomaticallySetToNull
});

after

builder.HasPrincipalProperty()
    .Relation(e => e.Color.Product)
    .PropertyMap(e => e.ProductName, e => e.Name)
    .PropertyMap(e => e.ProductAge, e => e.Age)
    .PropertyMap(e => e.ProductId, e => e.Id)
    .Conditional(condition =>
    {
        condition.WhereExpression = e => e.Type == SizeType.TypeA;
        condition.WhenNoInCondition = WhenNoInCondition.SetValueManually;
    });

這個例子裏面有點複雜, 不適合用作教學, 看看調用自己揣摩一下就好.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章