Null Object模式的目的包括:
1. 當對象提供者無法提供指定類型的對象時, 返回一個什麼都不做的對象, 這對調用者是透明的,並且調用者不用判斷獲得的對象是否爲null了,當然,對象提供者必須告知調用者(通過約定等).
2. 有時候需要傳遞一個什麼都不做的某個類型的對象給合作方. 例如某個函數需要實現特定接口的對象(通過參數傳入)進行某些操作, 該函數的調用者在某些情況下希望不進行這些操作,那麼他就可以傳進來一個實現了該接口但函數體全爲空的對象,這個對象就是Null Object.
舉個例子,從某處(不是通過new來創建)獲得一個對象後,我們的第一反應就是判斷這個對象是否爲null,這都成爲程序員的本能了。
如果爲null,則做一些特殊處理,就像下面的代碼片段:
if( recorder ==null ){
Log.error("Recorder對象爲空");
lastErrorCode =0;
}
else{
recorder.record("記錄點啥...");
}
看到了沒有,爲了處理這個對象爲null的情況,增加了很多行代碼,而且類似的代碼片段充斥在整個項目中,看着都想吐了。
要是EventRecorder的作者拍着胸脯向你保證:我給你的EventRecorder對象絕對不會是null!不然我生孩子沒.......
人家都這麼說了,那咱就應該相信他!
以後寫代碼就舒心多了,看着也清爽:
recorder.record("終於不用判斷是否爲NULL了.......");
Null Object模式就可以實現上面的約定。
下面是EventRecorder的聲明:
publicvoid record(String event);
}
增加兩個實現類:
publicvoid record(String event);
// 記錄內容到數據庫中
}
}
publicclass RecordEventToFile implements EventRecorder{
publicvoid record(String event);
// 記錄內容到文件中
}
}
下面是EventRecorderFactory中getRecorderByType的簡單實現:
EventRecorder recorder =null;
if(type ==0)
recorder =new RecordEventToDatabase();
elseif(type ==1)
recorder =new RecordEventToFile();
return recorder;
}
可以看出這個方法的返回值可能是null,調用者就需要判斷這種情況。
下面我們實現一個什麼都不做的EventRecorder:
publicvoid record(String event);
}
下面是修改後的getRecorderByType:
EventRecorder recorder =null;
if(type ==0)
recorder =new RecordEventToDatabase();
elseif(type ==1)
recorder =new RecordEventToFile();
else
recorder =new NullEventRecorder(); // 這就是Null Object
return recorder;
}
這樣就可以保證該方法的返回值永遠不會爲null了。
再舉一個例子來說明第二個目的:
publicinterface Payer {
publicvoid pay(int money);
}
// 使用信用卡付款
public PayerByCard implements Payer{
publicvoid pay(int money){
// 刷卡
}
}
// 不付款(這就是一個Null Object, 什麼都不做)
public NullPayer implements Payer{
publicvoid pay(int money){
}
}
下面是一個使用Payer對象的方法:
if(payer==null)
throw Exception;
payer.pay();
}
下面是一個使用場景:
if(userType =="黑社會老大")
payer =new NullPayer();
else
payer =new PayerByCard();
payer.pay();
// 享受服務....