Null Object
Problème
Nous souhaitons simplifier la gestion des références nulles pour éviter le risque de NullPointerException
.
Cas d'école
Nous avons l'interface MailerInterface
ci-après permettant d'envoyer des courriels :
interface MailerInterface {
public void sendMail(
String to,
String title,
String body
);
}
Nous souhaitons rendre optionnel l'envoi de ces courriels en fin de traitement. En première approche, nous pourrions procéder comme suit :
class MonTraitement {
private MailerInterface mailer ;
public MonTraitement(){
this.mailer = null ;
}
public void setMailer(MailerInterface mailer){
this.mailer = mailer ;
}
public void doSomething(){
//... traitement ...
if ( null != this.mailer ){
this.mailer.sendMail(
"admin@acme.org",
"Traitement des donnnées",
"Le traitement a été effectué."
);
}
}
}
Problème : Nous allons multiplier les contrôles null != this.mailer
et finir par oublier un cas.
Solution
- Créer un
NullMailer
ne faisant rien comme suit :
class NullMailer implements MailerInterface {
public void sendMail(
String to,
String title,
String body
){
// ne fait rien
}
}
- Initialiser
mailer
avec unNullMailer
plutôt quenull
class Client {
private MailerInterface mailer ;
public Client(){
this.mailer = new NullMailer() ;
}
public void setMailer(MailerInterface mailer){
assert( mailer != null );
this.mailer = mailer ;
}
public void doSomething(){
// traitement...
// Le contrôle sur this.mailer != null devient innutile
this.mailer.sendMail(
"admin@acme.org",
"Traitement des donnnées",
"Le traitement a été effectué."
);
}
}
Variantes
Nous soulignerons que :
- Une collection vide peut jouer le même rôle qu'un objet null (
this.points=null
->this.points=[]
) - Des valeurs particulières peuvent être utilisées pour modéliser un objet mathématique vide jouant le même rôle qu'un objet null :
{x: Number.NaN, y: Number.NaN}
pour une coordonnée 2D vide{lower: Number.POSITIVE_INFINITY, upper: Number.NEGATIVE_INFINITY}
pour un interval vide- ...
Penser à composer NullObject avec Singleton et ses variantes pour limiter le nombre d'objets créés :
NullMailer.getInstance()
Coordinate.EMPTY