🚫 Ad Blocker Detected

Please disable your AD blocker to continue using this site. Ads help us keep the content free! please press keyboard F5 to refresh page after disabled AD blocker

請關閉廣告攔截器以繼續使用本網站。廣告有助於我們保證內容免費。謝謝! 關閉後請按 F5 刷新頁面

0%

Null Object Pattern

前言:

假如在系統中null散佈在有許多地方且null有相對應的邏輯或行為.這時候就很適合使用NullObject Pattern來解決,已Null Object取代null邏輯.

Null可能引申出來問題

我們知道在.Net或Java中大部分都是參考類型,而null是參考類型的預設值,我們來看看以下程式.

1
2
Person p = null;
Console.WriteLine(p.Age);

如果物件p指向null且取得p.Age時就會throw NullReferenceException,所以我們在使用一些參考類型物件前都會先判斷此物件是否為null,在執行後續邏輯.

在系統中某一兩個地方這樣判斷還好,但如果一直重複這樣的判斷會造成程式碼不必要的膨脹….

相較於「不帶有null邏輯」的程式碼,面對null邏輯往往需要花費更多心力.

範例程式

下面有段程式碼在calculate方法中會判斷CartModel物件是否為null並執行相對應邏輯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class PaymentServiceNormal
{
public decimal calculate(CartModel model)
{
decimal result = 0m;
if (model == null)
return result;

result = model.Items.Sum(x => x.Price);

if (result > 400m)
result *= 0.8m;

return result;
}
}

我們可以將calculate方法提取出一個介面並對於null部份提取成一個類別實現此介面

能看到NullPayment這個類別已經被賦予相對應動作操作.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public interface IPaymentService
{
decimal calculate(CartModel model);
}

public class PaymentService : IPaymentService
{
public decimal calculate(CartModel model)
{
decimal result = model.Items.Sum(x => x.Price);

if (result > 400m)
result *= 0.8m;

return result;
}
}

public class NullPayment : IPaymentService
{
public decimal calculate(CartModel model)
{
return 0m;
}
}

在使用時我們就可統一判斷是否為null來給予相對應物件

這邊有點像是策略者模式(Strategy pattern),判斷要使用哪個邏輯,邏輯統一封裝到類別中.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Program
{
static void Main(string[] args)
{
CartModel model = null;
Console.WriteLine(Calculate(model));
Console.ReadKey();
}

static decimal Calculate(CartModel model)
{
var paymentService = model == null
? (IPaymentService)
new NullPayment()
: new PaymentService();
return paymentService.calculate(model);
}
}

NullObject Pattern缺點:

如果團隊工程師不知道目前程式碼已經存在NullObject實作,會寫出多餘的null測試.
如果目前系統只是需要少量對於null做判斷,這時導入NullObject會導致程式碼變得複雜.

小結:

假如系統中有許多地方需要判斷null並處理相對應的動作就很適合使用NullObject Pattern,但如果判斷null地方不是很多還是判斷就好了

程式碼範例

__此文作者__:Daniel Shih(石頭)
__此文地址__: https://isdaniel.github.io/nullobjectpattern/
__版權聲明__:本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 TW 許可協議。轉載請註明出處!

如果本文對您幫助很大,可街口支付斗內鼓勵石頭^^