大家好呀,今天也是设计模式冲冲冲!
今天带给大家的是空对象模式,纳尼?空对象模式是什么鬼?
空对象模式是行为型模式中的一种,行为型模式特别关注对象之间的通信。
空对象模式顾名思义,**使用一个空对象来取代对象为null的实例,并且可以提供在对象为null时的默认行为。**我们需要创建一个抽象类或者接口,然后两个具体的实现类,一个是空对象类,另一个则是正常实现的类。
光说可能很抽象,我们为什么要用空对象模式?它用在什么场景?连个场景都不举一个,简直就是在放pi,所以洪爵在这里给大家举一个栗子。
现在我们有一个场景,需要根据树的名字,返回对应的对象。那么就有如下的实现:
public class ConcreteTree {
private String name;
public ConcreteTree(String name) {
this.name = name;
}
public void callName() {
System.out.println("call " + name);
}
}
public class TreeFactory {
public ConcreteTree getTree(String treeName) {
ConcreteTree concreteTree = null;
switch (treeName) {
case "二叉树":
concreteTree = new ConcreteTree("二叉树");
break;
case "线段树":
concreteTree = new ConcreteTree("线段树");
break;
case "主席树":
concreteTree = new ConcreteTree("主席树");
break;
default:
break;
}
return concreteTree;
}
}
public class Client {
public static void main(String[] args) {
TreeFactory treeFactory = new TreeFactory();
ConcreteTree tree1 = treeFactory.getTree("线段树");
ConcreteTree tree2 = treeFactory.getTree("AVL树");
tree1.callName();
tree2.callName();
}
}
call 线段树
Exception in thread "main" java.lang.NullPointerException
at Null_Object_Pattern.Client.main(Client.java:14)
我们发现,当输入工厂中有的数据时,程序是能正常运行的,但是当工厂中没有该数据,那么就会返回null对象,正如我们写代码的时候,经常乐观的认为一个对象不为null,没有考虑问题的全面。
当遇到为null对象,就需要客户端对ConcreteTree做判断。
if(tree2 == null) {
// ...具体操作
}
一个客户端还好,如果多个客户端,或者说其他地方也要使用这个工厂去生成对应的树,岂不是每个地方都需要对它做判断?如果漏判了,则可能导致程序的崩溃。
这个时候最好的做法是把主动权交还给系统本身。我们来看一下,如果使用了空对象模式,是怎么避免程序可能出现的异常。
类图:
具体实现:
public interface Tree {
public boolean isNull();
public void callName();
}
public class NullTree implements Tree {
@Override
public boolean isNull() {
return true;
}
@Override
public void callName() {
System.out.println("未找到对应的树");
}
}
public class NotNullTree implements Tree {
private String name;
@Override
public boolean isNull() {
return false;
}
@Override
public void callName() {
System.out.println("call " + name);
}
}
public class TreeFactory {
public Tree getTree(String treeName) {
Tree concreteTree = null;
switch (treeName) {
case "二叉树":
concreteTree = new NotNullTree("二叉树");
break;
case "线段树":
concreteTree = new NotNullTree("线段树");
break;
case "主席树":
concreteTree = new NotNullTree("主席树");
break;
default:
concreteTree = new NullTree();
break;
}
return concreteTree;
}
}
public class Client {
public static void main(String[] args) {
TreeFactory treeFactory = new TreeFactory();
Tree tree1 = treeFactory.getTree("线段树");
Tree tree2 = treeFactory.getTree("AVL树");
tree1.callName();
tree2.callName();
}
}
/*
call 线段树
未找到对应的树
*/
ok,通过使用空对象模式,我们能加强系统稳定性,有效的防止空指针报错影响系统。并且能对空对象的情况定制化的输出,掌握主动权。并不会依靠客户端来保证系统的稳定运行。通过isNull()对 == null进行替换,更加的形象。
好的,本篇空对象模式就介绍到这里。
愿每个人都能带着怀疑的态度去阅读文章并探究其中原理。
道阻且长,往事作序,来日为章。
期待我们下一次相遇!