需要再三检查对象是否为null。
将null值替换为null对象。
动机:
当某个字段是null时,多态可以扮演另一个较不直观的用途。
控对象一定是常量,它们的任何成分都不会发生变化。
做法:
为源类建立一个子类,使其行为就像是源类的null版本。在源类和null子类中都加上isNull()函数,前者的isNull()应该返回false,后者的isNull()应该返回true。
=》建立一个nullable接口,将isNull()函数放在其中,让源类实现这个接口。
=》建立一个测试接口,专门用来检查对象是否为null。
找出所有“索求源对象却获得一个null”的地方。修改这些地方,使它们改而获得一个控对象。
找出所有“将源对象与null做比较”的地方。修改这些地方,使它们调用isNull函数。
找出这样的程序点:如果对象不是null,做A动作,否则B动作。
对于每一个上述地点,在null类中覆写A动作,使其行为和B动作相同。
使用上述被覆写的动作,然后删除“对象是否等于null”的条件测试。
旧代码
class Site...
Customer getCustomer(){
return _customer();
}
Customer _customer;
class Customer...
public String getName(){...}
public BillingPlan getPlan(){...}
public PaymentHistory getHistory(){...}
class PaymentHistory...
int getWeeksDelinguentInLastYear()
Customer customer = site.getcustomer();
BillingPlan plan;
if(customer == null) plan = BillingPan.basic();
else plan = customer.getPlan();
String customerName;
if(customer == null) customerName = "occupant";
else customerName = customer.getName();
int weeksDelinquent;
if(customer == null) weeksDelinquent = 0;
else weeksDelinquent = customer.getHistory().getWeeksDelinquentInLastYear();
新代码
class NullCustomer extends customer{
public boolean isNull(){
return true;
}
public String getName(){
return "occupant";
}
public void setPlan(BillingPlan arg){
...
}
public PaymentHistory getHistory() {
return PaymentHistory.newNull();
}
}
class NullPaymentHistory extends PaymentHistory...
int getWeeksDelinquentInLastYear(){
return 0;
}
class Customer...
public boolean isNull(){
return false;
}
static Customer newNull(){
return new NullCustomer();
}
protected Customer(){}
interface Nullable{
boolean isNull();
}
class customer implements Nullable
String customerName = customer.getName();