1.此文章讨论在构建Java对象时遇到多参数问题(有些是非必须的)如何进行合理的构建。
2.遇到这种情况有三种处理方式:
- 重叠构造器:
- JavaBean模式
- 建造者(Builder)模式
创建的虚拟实体类为Book类,其中:
//必需的参数
private String bookName;
private float price;
//以下为非必需的参数
private String authorName;
private String bookPublishing;
private String classify;
3.重叠构造器模式:
在这种模式下,提供第一个构造器只有必要的参数,第二个构造器有一个可选的参数,第三个构造器有两个可选的参数,依次类推,最后一个构造器包含全部参数。
/**
* 1.使用重载构造器的方法初始化对象的多个属性
*/
public class Book {
//require parameters
private String bookName;
private float price;
//notrequire parameters
private String authorName;
private String classify;
private String bookPublishing;
/*
overlode constructor
*/
//必要参数的构造器
public Book(String bookName, float price){
this.bookName = bookName;
this.price = price;
}
//含一个可选参数的构造器
public Book(String bookName, float price, String authorName){
this.bookName = bookName;
this.price = price;
this.authorName = authorName;
}
//含两个可选参数的构造器
public Book(String bookName, String authorName, float price, String classify){
this.bookName = bookName;
this.authorName = authorName;
this.price = price;
this.classify = classify;
}
//含三个可选参数的构造器
public Book(String bookName, String authorName, float price, String classify, String bookPublishing){
this.bookName = bookName;
this.authorName = authorName;
this.price = price;
this.classify = classify;
this.bookPublishing = bookPublishing;
}
//方便打印数据
@Override
public String toString() {
return "Book{" +
"bookName='" + bookName + '\'' +
", authorName='" + authorName + '\'' +
", price=" + price +
", classify='" + classify + '\'' +
", bookPublishing='" + bookPublishing + '\'' +
'}';
}
}
下面为使用的时候如何进行构造:
- 创建只包含两个必要参数的对象
//创建只知道书名和价钱的对象
Book book1 = new Book("Java", 25);
System.out.println(book1);
结果为:
- 创建包含一个可选参数的对象:
//包含可选参数authorName
Book book2 = new Book("C++", 21, "谭浩强");
System.out.println(book2);
结果为:
- 创建包含全部参数的对象
Book book3 = new Book("数据结构", "严蔚敏", 20, "计算机系列丛书", "清华大学出版社");
System.out.println(book3);
结果为:
但是当我们需要设置bookName, price, authorName, bookPublishing 时会遇到下面的情况:
Book book4 = new Book("操作系统", 30, "冯裕忠", null, "清华大学出版社");
//此时因为不知道 classify 属性的值,也没有仅含已知参数的构造器,所以不得不对 classify 传递 null 值。
且随着参数的增多,它很快会失去控制。
总结:重叠构造器是可行的,但是当有许多参数时,客户端代码会很难写,并且阅读困难。
4.JavaBean模式:
在这中模式下,先调用一个无参构造器来创建对象,然后调用set方法设置每个必要的值,以及每个可选的参数。
/**
* 使用JavaBean模式创建对象
* 有些属性是可选的
*/
public class Book {
//require parameters
private String bookName;
private float price;
//notrequire parameters
private String authorName;
private String classify;
private String bookPublishing;
/*
提供一个空的构造器
*/
public Book(){};
/*
设置属性的set方法
*/
public void setBookName(String bookName) {
this.bookName = bookName;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
public void setPrice(float price) {
this.price = price;
}
public void setClassify(String classify) {
this.classify = classify;
}
public void setBookPublishing(String bookPublishing) {
this.bookPublishing = bookPublishing;
}
//重写toString方法。
@Override
public String toString() {
return "BookBean{" +
"bookName='" + bookName + '\'' +
", authorName='" + authorName + '\'' +
", price=" + price +
", classify='" + classify + '\'' +
", bookPublishing='" + bookPublishing + '\'' +
'}';
}
}
创建对象的代码为:
//先调用无参构造创建对象
Book book = new Book();
//然后调用set方法对需要的参数进行赋值
book.setBookName("Java");
book.setPrice(30);
book.setAuthorName("李兴华");
特点:创建容易,但是把构造过程分为几个调用中,易使JavaBean对像处于不一致的状态。
5.构建者(builder)模式
不直接生成对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂)得到一个Buiding对象。然后在Building对象上调用类似的set方法来设置每个可选的参数。最后客户端调用无参的build方法来生成对象,代码如下:
public class Book {
//必需的参数
private String bookName;
private float price;
//以下为非必需的参数
private String authorName;
private String bookPublishing;
private String classify;
//设置私有构造器,传递一个内部类参数,允许内部类调用
private Book(Building builder){
this.bookName = builder.bookName;
this.authorName = builder.authorName;
this.price = builder.price;
this.bookPublishing = builder.bookPublishing;
this.classify = builder.classify;
}
//自定义Building内部类
public static class Building{
//必需的参数
private String bookName;
private float price;
//以下为非必需的参数
private String authorName;
private String bookPublishing;
private String classify;
//必要参数构造一个Building对象
public Building(String bookName, float price){
this.bookName = bookName;
this.price = price;
}
//把Building对象传递给外部的Book构造器
public Book build(){
return new Book(this);
}
//设置可选参数
public Building authorName(String authorName){
this.authorName = authorName;
return this;
}
public Building bookPublishing(String bookPublishing){
this.bookPublishing = bookPublishing;
return this;
}
public Building classify(String classify){
this.classify = classify;
return this;
}
}
//重写toString便于输出
@Override
public String toString() {
return "Book{" +
"bookName='" + bookName + '\'' +
", price=" + price +
", authorName='" + authorName + '\'' +
", bookPublishing='" + bookPublishing + '\'' +
", classify='" + classify + '\'' +
'}';
}
}
客户端使用为:
Book book = new Book.Building("机器学习", 35).authorName("周志华").bookPublishing("清华大学出版社").classify("深度学习系类丛书").build();
System.out.println(book);
输出为: