注册 | 登录 忘记密码? 51cto首页 | 博客 | 论坛 | 招聘
热点文章 [业内传闻]今天,7月25日..
 帮助

如何运用Null Object模式


2008-03-29 14:18:29
 标签:模式 Null   [推送到技术圈]

版权声明:原创作品,如需转载,请与作者联系。否则将追究法律责任。
        Null Object模式本质上是Strategy模式的一种应用。当需要频繁的判断对象是否为null时,可以考虑使用Null Object模式。
现在假设一个旅馆管理系统,建立一个Person类存储住客的相关信息,建立一个Plan类存储住客入住和离开的时间信息。
Person.java
package com.zj.person;
 
import java.util.Date;
import com.zj.plan.Plan;
 
public class Person {
    private final String name;
    private final String ID;
    private Plan plan;  
   
    public Person(String name,String id,Date checkOut){
       this.name=name;
       ID=id;
       plan=new Plan(checkOut);
    }
 
    public String getCheckIn() {
       return plan.getCheckIn().toString();
    }
   
    public String getCheckOut() {
       return plan.getCheckOut().toString();
    }
   
    public void changeCheckOut(Date date){
       plan.setCheckOut(date);
    }
 
    public String getName() {
       return name;
    }
 
    public String getID() {
       return ID;
    }
   
    public String toString(){
       return name+"-"+ID;
    }
}
 
Plan.java
package com.zj.plan;
 
import java.util.Date;
 
public class Plan {
    private final Date checkIn;
    private Date checkOut;
 
    public Plan(Date checkOut) {
       checkIn = new Date();
       this.checkOut = checkOut;
    }
 
    public Date getCheckOut() {
       return checkOut;
    }
 
    public void setCheckOut(Date checkOut) {
       this.checkOut = checkOut;
    }
 
    public Date getCheckIn() {
       return checkIn;
    }
 
    public String toString() {
       return checkIn + "-" + checkOut;
    }
}
 
现在,设计旅馆房间类Room,由于不知道该房间当前是否有人入住,所以每次取信息时都需要判断Customer是否为null
Room.java
package com.zj.person;
 
public class Room {
    private Person customer;
 
    public Room() {}
 
    public Room(Person person) {
       customer = person;
    }
 
    public String getCustomer() {
       return customer.toString();
    }
 
    public void setCustomer(Person customer) {
       this.customer = customer;
    }
 
    public String getCustomerName() {
       if (customer == null)
           return "No Customer";
       return customer.getName();
    }
 
    public String getStartTime() {
       if (customer == null)
           return "N/A";
       return customer.getCheckIn();
    }
 
    public String getEndTime() {
       if (customer == null)
           return "N/A";
       return customer.getCheckOut();
    }
 
    public void checkOut() {
       customer = null;
    }
}
 
现在使用Null Object模式改写上面的例子,避免多次if (customer == null)的判断。
先定义一个接口,表示该类是实现Null Object模式的类。
<<interface>>Nullable.java
package com.zj.nullObject;
 
public interface Nullable {
    boolean isNull();
}
 
改写Person.java,提供一个内部类NullPerson给出在Personnull的情况下的所有实现,并通过单例方式提供它的唯一实例。
Person.java
package com.zj.nullperson;
 
import java.util.Date;
import com.zj.nullObject.Nullable;
import com.zj.plan.Plan;
 
class Person implements Nullable{
    private final String name;
    private final String ID;
    private final Plan plan;
    private final boolean nullable;
    public static final Person NULL = new NullPerson();//singleton
 
    public Person(String name,String id,Plan plan){
       this.name=name;
       ID=id;
       this.plan=plan;
       nullable=false;
    }
 
    public String getCheckIn() {
       return plan.getCheckIn().toString();
    }
   
    public String getCheckOut() {
       return plan.getCheckOut().toString();
    }
   
    public void changeCheckOut(Date date){
       plan.setCheckOut(date);
    }
 
    public String getName() {
       return name;
    }
 
    public String getID() {
       return ID;
    }
   
    public String toString(){
       return name+"-"+ID;
    }
   
    public boolean isNull(){
       return nullable;
    }
   
    public static class NullPerson extends Person implements Nullable {
       private NullPerson(){
           super("N/A","N/A",null);
       }
      
       public String getCheckIn() {
           return "N/A";
       }
      
       public String getCheckOut() {
           return "N/A";
       }
      
       public boolean isNull(){
           return true;
       }
    }
}
 
此时,Room类就可以避免繁杂的null判断了。因为在赋值成员变量customer时,都已经判断是否为null person,如果是的话,则提供NullPerson的实例。
Room.java
package com.zj.nullperson;
 
public class Room {
    private Person customer;
 
    public Room() {
       if (customer.isNull())
           customer = Person.NULL;
    }
 
    public Room(Person person) {
       if (person.isNull())
           customer = Person.NULL;
       customer = person;
    }
 
    public String getCustomer() {
       return customer.toString();
    }
 
    public void setCustomer(Person person) {
       if (person.isNull()) {
           customer = Person.NULL;
           return;
       }
       customer = person;
    }
 
    public String getCustomerName() {
       return customer.getName();
    }
 
    public String getStartTime() {