當代碼中過度出現需要檢查 null (空值) 的情況,可以考慮使用 Null Object Pattern 取代相關的判斷式。

 
Account 為代表帳號的類別, e.g.

public class Account {
    private String mName;
    public Account(String name) {
        mName = name;
    }
    public String getName() {
        return mName;
    }
}

 
在客戶端需要常常檢查 Account 是否為空值才能進行下一步動作。e.g.

Account account = bank.getAccount();
if(account != null)
{
     //use account do something
}

 
重複檢查是否為 null,也是一種 Duplicated Code 的壞味道。
首先建立 NullAccount 來代表 Account 的 Null Object e.g.

public Account {
...
    private class NullAccount extends Account {
        private NullAccount(String name) {
            super(name);
        }
        @Override
        public String getName() {
            return "No name , This is NullAccount";
        }
    }
...
}

這裡使用了內部類別,是因為 NullAccount 為 Account 的一種型態,當然也可以轉換成獨立的 public 類別。
第11行修改了原有的方法,只要是在Account中所有的功能都必須被覆寫,以區別 NullAccount。
接著在 Account 加入讓外部取得 NullAccount 的方法 e.g.

public class Account {
...
    public static Account getNullAccount() {
            return new Account(null).new NullAccount(null);
    }
...
}

 
最後完整的 Account 如下

public class Account {
    private String mName;
    public Account(String name) {
        mName = name;
    }
    public String getName() {
        return mName;
    }
    public static Account getNullAccount() {
        return new Account(null).new NullAccount(null);
    }
    private class NullAccount extends Account {
        private NullAccount(String name) {
            super(name);
        }
        @Override
        public String getName() {
            return "No name , This is NullAccount";
        }
    }
}

 
修改 “所有” 會回傳 Account 的位置讓其返回 NullAccount,注意是所有會返回 Account 位置都必須修改!!
如原本 Bank 的 getAccount() 為

public class Bank {
...
    public Account getAccount()
    {
        return mAccount;
    }
...
}

改為

public class Bank {
...
    public Account getAccount()
    {
        return (mAccount == null) ? Account.getNullAccount() : mAccount;
    }
...
}

 
再也不需要檢查從 Bank 取的 Account 是否為 null 了

Account account = bank.getAccount();
String name = account.getName();

 
Note :
1. 使用 Null Object Pattern 只有在大量檢查空值的情況下才有用,若外部檢查的位置不多,使用這個 Pattern 的實質效益不大。
2. 以上為 Null Object Pattern 的基本型態,事實上 Null Object 本身可以修改為 Singleton Pattern
為了避免產生重複的實體,讓外部存取單一實體即可。
Singleton Null Object Pattern
修改 NullAccount e.g.

    private static class NullAccount extends Account {
        private static NullAccount sUniqueInstance = new NullAccount(null);
        private NullAccount(String name) {
            super(name);
        }
        public static NullAccount getInstance() {
            return sUniqueInstance;
        }
        @Override
        public String getName() {
            return "No name , This is NullAccount";
        }
    }

 
修改 Account 對外的介面 e.g.

public Account {
...
    public static Account getNullAccount() {
            return NullAccount.getInstance();
    }
...
}

如此產生的 Null Object 實體都是相同的。
 
3. Null Object Pattern 其實為 Special Case Pattern 的其中一種。
Special Case Pattern 請參考 patterns of enterprise application architecture(企業應用架構模式)。