空对象设计模式 -- 《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有误
参数有误,无法查询到此员工

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

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

小结

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

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

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BaymaxCS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值