近日第一次听闻这种很有意思的设计模式–空对象设计模式,鲜有人提起,特此记录。
当我们在实际开发过程中,经常会遇到需要对某个对象进行非空判断。多次的非空判断会让代码显得枯燥,倘若在某处遗忘了非空判断,还会导致空指针异常。
这时,可以考虑使用空对象设计模式来优化这个问题。
空对象并非拥有“真实”的值,但它拥有“真实”对象的行为,在此模式下默认所有对象都是有效的,不必浪费精力去检查 NULL。
例如,我们现在有一个 Staff 员工类,一个管理员工信息的 StaffManagement 类,本例中采用 Map 来模拟数据库操作。
public class Staff {
private String ID;
private String name;
private String post;
private String tel;
public String getID() {
return ID;
}
public String getName() {
return name;
}
public String getPost() {
return post;
}
public String getTel() {
return tel;
}
}
public class StaffManagement {
public static final Map<String, Staff> staffDB = new HashMap<>();
//模拟测试数据
static {
staffDB.put("1", new Staff("1", "Tom", "Marketing Manager", "0731-123456"));
staffDB.put("2", new Staff("2", "Tom", "Product Manager", "0731-222222"));
staffDB.put("3", new Staff("3", "Tom", "Software Engineer", "0731-333333"));
}
public Staff getStaff(String id) {
return staffDB.get(id);
}
public void queryStaffName(String id) {
Staff staff = getStaff(id);
if (staff != null) {
System.out.println(staff.getName());
}
}
public void queryStaffPost(String id) {
Staff staff = getStaff(id);
if (staff != null) {
System.out.println(staff.getPost());
}
}
public void queryStaffTel(String id) {
Staff staff = getStaff(id);
if (staff != null) {
System.out.println(staff.getTel());
}
}
public static void main(String[] args) {
StaffManagement management = new StaffManagement();
String id = "1";
management.queryStaffName(id);
management.queryStaffPost(id);
management.queryStaffTel(id);
}
}
Tom
Marketing Manager
0731-123456
上例在获取员工姓名、岗位、联系方式的场景下,都需要在每个方法下进行非空判断,代码显得非常繁琐。
接下来,我们引入空对象设计模式,将代码进行一番改造。
因空对象都是单例,故在 Staff 类中创建 NullStaff 内部类,并对外暴漏 Staff.NULL
引用。
public class Staff {
private String ID;
private String name;
private String post;
private String tel;
public String getID() {
return ID;
}
public String getName() {
return name;
}
public String getPost() {
return post;
}
public String getTel() {
return tel;
}
public Staff(String ID, String name, String post, String tel) {
this.ID = ID;
this.name = name;
this.post = post;
this.tel = tel;
}
@Override
public String toString() {
return "Staff{" +
"ID='" + ID + '\'' +
", name='" + name + '\'' +
", post='" + post + '\'' +
", tel='" + tel + '\'' +
'}';
}
public static class NullStaff extends Staff {
public static String msg = "参数有误,无法查询到此员工";
public NullStaff() {
super(msg, msg, msg, msg);
}
}
public static final Staff NULL = new NullStaff();
}
public class StaffManagement {
public static final Map<String, Staff> staffDB = new HashMap<>();
//模拟测试数据
static {
staffDB.put("1", new Staff("1", "Tom", "Marketing Manager", "0731-123456"));
staffDB.put("2", new Staff("2", "Tom", "Product Manager", "0731-222222"));
staffDB.put("3", new Staff("3", "Tom", "Software Engineer", "0731-333333"));
}
public Staff getStaff(String id) {
Staff staff = staffDB.get(id);
if (staff == null) {
System.out.println("参数 ID:" + id + "有误");
return Staff.NULL;
} else {
return staff;
}
}
public void queryStaffName(String id) {
Staff staff = getStaff(id);
System.out.println(staff.getName());
}
public void queryStaffPost(String id) {
Staff staff = getStaff(id);
System.out.println(staff.getPost());
}
public void queryStaffTel(String id) {
Staff staff = getStaff(id);
System.out.println(staff.getTel());
}
public static void main(String[] args) {
StaffManagement management = new StaffManagement();
String id = "-1";
management.queryStaffName(id);
management.queryStaffPost(id);
management.queryStaffTel(id);
}
}
参数 ID:-1有误
参数有误,无法查询到此员工
参数 ID:-1有误
参数有误,无法查询到此员工
参数 ID:-1有误
参数有误,无法查询到此员工
现在我们即使不进行非空判断,也不会抛出空指针异常。
需要注意的是,为避免生吞空指针异常,最好通过日志记录下错误的参数,便于日后排查。
小结
- 空对象设计模式可应用于对象需要多次非空判断的场景
- 客户端传入的参数不一定合法,空对象设计模式可增强系统的可靠性
- 参数错误信息推荐使用日志进行记录
本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。
若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!