空对象设计模式 -- 《JAVA编程思想》48

近日第一次听闻这种很有意思的设计模式–空对象设计模式,鲜有人提起,特此记录。

当我们在实际开发过程中,经常会遇到需要对某个对象进行非空判断。多次的非空判断会让代码显得枯燥,倘若在某处遗忘了非空判断,还会导致空指针异常。

这时,可以考虑使用空对象设计模式来优化这个问题。

空对象并非拥有“真实”的值,但它拥有“真实”对象的行为,在此模式下默认所有对象都是有效的,不必浪费精力去检查 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有误
参数有误,无法查询到此员工

现在我们即使不进行非空判断,也不会抛出空指针异常。

需要注意的是,为避免生吞空指针异常,最好通过日志记录下错误的参数,便于日后排查。

小结

  • 空对象设计模式可应用于对象需要多次非空判断的场景
  • 客户端传入的参数不一定合法,空对象设计模式可增强系统的可靠性
  • 参数错误信息推荐使用日志进行记录

本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。

若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!

Guess you like

Origin blog.csdn.net/BaymaxCS/article/details/120005961