美文网首页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