GoF著作中未提到的设计模式(3):Null Object

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();

//  享受服务....
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值