咱們常見的一個例子java
Employee employee = DB.getEmployee("bob"); if(employee!=null && employee.isTimeToPay(today)){ employee.pay(); }
這個是從DB中取得名稱爲bob的僱員,若是取獲得了,而且今天是發薪日,則會支付。咱們會常常寫這種判斷對象爲空的代碼,這種寫法不只醜陋並且很是容易出錯,若是咱們有些地方沒有判斷而調用了空對象的屬性或者方法,將會拋出NullpointException,那若是咱們不使用這種判斷而在DB的getEmployee方法中拋出異常的方式,這樣講會變得更加麻煩,咱們須要把相關代碼用try catch包括起來,而後還得進行處理。ide
這種狀況咱們可使用NULL OBJECT模式來解決這些問題,一般改模式會消除對null值進行檢查的須要,而且有助於代碼的簡化。測試
大體的思路是咱們有兩個實現了Employee接口的對象,一個是正常的EmployeeImp,另一個是空的對象NullEmployee,當DB中取不到名字爲bob的對象時,會返回NullEmployee對象。NullEmployee實現了Employee中的全部方法,可是方法中「什麼也沒作」,「什麼也沒作」的含義和具體的方法語境有關。例如,有人會指望isTimeToPay方法被實現爲返回false,由於根本不會爲NullEmployee支付薪水。
使用這個模式,最初的代碼會更改成這樣:spa
Employee employee = DB.getEmployee("bob"); if(employee.isTimeToPay(today)) employee.pay();
這種代碼既不容易出錯,也不醜陋。而且具備很好的一致性。DB.getEmployee中總會返回一個Employee的實例,無論是否找獲得僱員,均可以保證返回的實例具備合適的行爲。
固然,在不少狀況下,仍然想要知道是否DBEmployee沒有招到僱員。在Employee中建立持有惟一NullEmployee實例的static final變量就能夠達到這個目的。
測試程序:
code
Public void testNull() throws Exception{ Employee e = DB.getEmployee(「bob」); if(e.isTimeToPay(new Date())){ fail(); } assertEquals(Employee.NULL,e); }
下面程序展現了DB類。爲了方便測試,getEmployee方法只返回EmployeeNULL。對象
Public class DB{ Public static Employee getEmployee(String name) { Return Employee.NULL; } }
接下來程序就是展現Employee接口。該接口中有一個名爲NULL的靜態變量,持有一個匿名的實現體是無效僱員(NULL Employee)類惟一的實例,其中isTimeToPay返回false,pay方法則爲空。
接口
import java.util.Date; /** * Created by wangtf on 2015/12/22. */ public interface Employee { public boolean isTimeToPay(Date date); public void pay(); public static Employee NULL = new Employee() { @Override public boolean isTimeToPay(Date date) { return false; } @Override public void pay() { } }; }
使無效僱員類成爲一個匿名內部類是一種確保該類只有一個單一實例的方法。實際上並不存在NullEmployee類自己。其餘任何人都沒法建立無效僱員的其餘實例。這是很是好的,由於咱們指望的表達方式是:
if(e==Employee.NULL)
若是能夠建立無效僱員的多個實例,那麼這種表達方式就是部可靠的get