Null Object模式的目的包括:

1. 当对象提供者无法提供指定类型的对象时, 返回一个什么都不做的对象, 这对调用者是透明的,并且调用者不用判断获得的对象是否为null了,当然,对象提供者必须告知调用者(通过约定等).

2. 有时候需要传递一个什么都不做的某个类型的对象给合作方. 例如某个函数需要实现特定接口的对象(通过参数传入)进行某些操作, 该函数的调用者在某些情况下希望不进行这些操作,那么他就可以传进来一个实现了该接口但函数体全为空的对象,这个对象就是Null Object.


  举个例子,从某处(不是通过new来创建)获得一个对象后,我们的第一反应就是判断这个对象是否为null,这都成为程序员的本能了。

如果为null,则做一些特殊处理,就像下面的代码片段:

EventRecorder recorder = EventRecorderFactory.getRecorderByType(0);
if( recorder == null ){
Log.error(
"Recorder对象为空");
lastErrorCode
= 0;
}
else{
recorder.record(
"记录点啥...");
}

看到了没有,为了处理这个对象为null的情况,增加了很多行代码,而且类似的代码片段充斥在整个项目中,看着都想吐了。  

要是EventRecorder的作者拍着胸脯向你保证:我给你的EventRecorder对象绝对不会是null!不然我生孩子没.......

人家都这么说了,那咱就应该相信他!

以后写代码就舒心多了,看着也清爽:

EventRecorder recorder = EventRecorderFactory.getRecorderByType(0);
recorder.record(
"终于不用判断是否为NULL了.......");

Null Object模式就可以实现上面的约定。

下面是EventRecorder的声明:
 

public interface EventRecorder{
public void record(String event);
}

增加两个实现类:
 
public class RecordEventToDatabase implements EventRecorder{
public void record(String event);
// 记录内容到数据库中
}
}

public class RecordEventToFile implements EventRecorder{
public void record(String event);
// 记录内容到文件中
}
}

下面是EventRecorderFactory中getRecorderByType的简单实现:
 
public static EventRecorder getRecorderByType(int type){
EventRecorder recorder
= null;
if(type == 0)
recorder
= new RecordEventToDatabase();
else if(type == 1)
recorder
= new RecordEventToFile();
return recorder;
}


可以看出这个方法的返回值可能是null,调用者就需要判断这种情况。

下面我们实现一个什么都不做的EventRecorder:

public class NullEventRecorder implements EventRecorder{
public void record(String event);
}

下面是修改后的getRecorderByType:
 
public static EventRecorder getRecorderByType(int type){
EventRecorder recorder
= null;
if(type == 0)
recorder
= new RecordEventToDatabase();
else if(type == 1)
recorder
= new RecordEventToFile();
else
recorder
= new NullEventRecorder(); // 这就是Null Object
return recorder;
}

这样就可以保证该方法的返回值永远不会为null了。

 再举一个例子来说明第二个目的:

// 付款人接口

public interface Payer {

public void pay(int money);

}

// 使用信用卡付款

public PayerByCard implements Payer{

public void pay(int money){

// 刷卡

}

}

// 不付款(这就是一个Null Object, 什么都不做)

public NullPayer implements Payer{

public void pay(int money){

}

}

下面是一个使用Payer对象的方法:

public void pay(Payer payer){

if(payer==null)

throw Exception;

payer.pay();

}

下面是一个使用场景:

Payer payer = null;

if(userType == "黑社会老大")

payer
= new NullPayer();

else

payer
= new PayerByCard();

payer.pay();

// 享受服务....

作者: West_Link 发表于 2011-07-08 09:44 原文链接

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"