美文网首页Java学习笔记
《effective java》读书笔记——遇到多个构造器参数时

《effective java》读书笔记——遇到多个构造器参数时

作者: 小小浪把_Dont_know拍 | 来源:发表于2017-09-03 20:49 被阅读26次

    在日常工作中,业务场景会非常复杂。为了满足对应的业务场景,我们需要同时兼容多种情况。

    业务背景

    账号体系支持多种用户身份,对于这种需求,本应该生成一个全局唯一的id。但是由于原先的设计不太优雅,我们需要适配原先的业务场景。

    1. 手机号身份,这是内部注册的账号,buyerId。
    2. 其他app账号绑定,例如微信、qq、微博,fansType和fansId。

    用户类

    public class User {
        private long buyerId;
        private int fansType;
        private long fansId;
    
        public long getBuyerId() {
            return buyerId;
        }
    
        public void setBuyerId(long buyerId) {
            this.buyerId = buyerId;
        }
    
        public int getFansType() {
            return fansType;
        }
    
        public void setFansType(int fansType) {
            this.fansType = fansType;
        }
    
        public long getFansId() {
            return fansId;
        }
    
        public void setFansId(long fansId) {
            this.fansId = fansId;
        }
    }
    

    问题:需要了解业务细节,没有规则约束,容易遗漏字段

    多个构造器参数类

    public class User {
        private final long buyerId;
        private final int fansType;
        private final long fansId;
    
        public User(long buyerId) {
            this.buyerId = buyerId;
            this.fansType = 0;
            this.fansId = 0;
        }
    
        public User(int fansType, long fansId) {
            this.buyerId = 0;
            this.fansType = fansType;
            this.fansId = fansId;
        }
    
        public User(long buyerId, int fansType, long fansId) {
            this.buyerId = buyerId;
            this.fansType = fansType;
            this.fansId = fansId;
        }
    }
    

    问题:构造方法太多,不利于后续维护

    业务需求变化

    产品说,我们需要支持匿名用户。构造器参数又得增加一倍,程序员的恶梦开始了。

    用构建器改造

    public class Builder {
        private long buyerId;
        private int fansType;
        private long fansId;
    
        public long getBuyerId() {
            return buyerId;
        }
    
        public void setBuyerId(long buyerId) {
            this.buyerId = buyerId;
        }
    
        public int getFansType() {
            return fansType;
        }
    
        public void setFansType(int fansType) {
            this.fansType = fansType;
        }
    
        public long getFansId() {
            return fansId;
        }
    
        public void setFansId(long fansId) {
            this.fansId = fansId;
        }
    
        public User build() {
            if (buyerId == 0 && fansType == 0 && fansId == 0) {
                throw new RuntimeException("please init user data");
            }
            if (fansId != 0 && fansType == 0) {
                throw new RuntimeException("invalid fans type");
            }
            if (fansType != 0 && fansId == 0) {
                throw new RuntimeException("invalid fans id");
            }
            return new User(this);
        }
    
    }
    public class User {
        private final long buyerId;
        private final int fansType;
        private final long fansId;
    
        User(Builder builder) {
            buyerId = builder.getBuyerId();
            fansType = builder.getFansType();
            fansId = builder.getFansId();
        }
    }
    

    问题:不够内聚

    内部类

    public class User {
        private final long buyerId;
        private final int fansType;
        private final long fansId;
    
        private User(Builder builder) {
            buyerId = builder.buyerId;
            fansType = builder.fansType;
            fansId = builder.fansId;
        }
    
        public static class Builder {
            private long buyerId;
            private int fansType;
            private long fansId;
    
            public Builder buyerId(long buyerId) {
                this.buyerId = buyerId;
                return this;
            }
    
            public Builder fansType(int fansType) {
                this.fansType = fansType;
                return this;
            }
    
            public Builder fansId(long fansId) {
                this.fansId = fansId;
                return this;
            }
    
            public User build() {
                if (buyerId == 0 && fansType == 0 && fansId == 0) {
                    throw new RuntimeException("please init user data");
                }
                if (fansId != 0 && fansType == 0) {
                    throw new RuntimeException("invalid fans type");
                }
                if (fansType != 0 && fansId == 0) {
                    throw new RuntimeException("invalid fans id");
                }
                return new User(this);
            }
    
        }
    }
    

    优点:灵活控制入参,便于后续扩展。
    这就是设计模式中的builder模式。

    使用构建器

    public class Main {
    
        public static void main(String[] args) throws Exception {
            User buyer = new User.Builder().buyerId(1L).build();
            User fans = new User.Builder().fansType(1).fansId(1L).build();
        }
    }
    

    适应变化

    这个时候,如果产品提出支持匿名用户的需求,我们就可以从容应对了:

    public class User {
        private final long buyerId;
        private final int fansType;
        private final long fansId;
        private final String nobody;
    
        private User(Builder builder) {
            buyerId = builder.buyerId;
            fansType = builder.fansType;
            fansId = builder.fansId;
            nobody = builder.nobody;
        }
    
        public static class Builder {
            private long buyerId;
            private int fansType;
            private long fansId;
            private String nobody;
    
            public Builder buyerId(long buyerId) {
                this.buyerId = buyerId;
                return this;
            }
    
            public Builder fansType(int fansType) {
                this.fansType = fansType;
                return this;
            }
    
            public Builder fansId(long fansId) {
                this.fansId = fansId;
                return this;
            }
    
            public Builder nobody(String nobody) {
                this.nobody = nobody;
                return this;
            }
    
            public User build() {
                if (buyerId == 0 && fansType == 0 && fansId == 0 && nobody.equals("")) {
                    throw new RuntimeException("please init user data");
                }
                if (fansId != 0 && fansType == 0) {
                    throw new RuntimeException("invalid fans type");
                }
                if (fansType != 0 && fansId == 0) {
                    throw new RuntimeException("invalid fans id");
                }
                return new User(this);
            }
    
        }
    }
    

    参考资料

    《effective java》

    相关文章

      网友评论

        本文标题:《effective java》读书笔记——遇到多个构造器参数时

        本文链接:https://www.haomeiwen.com/subject/trgjjxtx.html