建造模式
介紹
該子標題中內容,來源菜鳥教程
意圖
將一個複雜的構建與其表示相分離,使得同樣的構建過程可以創建不同的表示。
主要解決
主要解決在軟件系統中,有時候面臨着"一個複雜對象"的創建工作,其通常由各個部分的子對象用一定的算法構成;由於需求的變化,這個複雜對象的各個部分經常面臨着劇烈的變化,但是將它們組合在一起的算法卻相對穩定。
何時使用
一些基本部件不會變,而其組合經常變化的時候。
如何解決
將變與不變分離開。
優點
-
建造者獨立,易擴展。
-
便於控制細節風險。
缺點:
-
產品必須有共同點,範圍有限制。
-
如內部變化複雜,會有很多的建造類。
使用場景
-
需要生成的對象具有複雜的內部結構。
-
需要生成的對象內部屬性本身相互依賴。
注意事項
與工廠模式的區別是:建造者模式更加關注與零件裝配的順序。
代碼
模式角色和職責
產品對象
複雜的內部屬性集合的bean。
本文的例子:Company和CompanyPersonnel對象
抽象構建類
主要用來對產品的屬性進行構建
本文的例子:CompanyBuilder對象
具體的構建類
該類實現 【抽象構建類】 ,對產品中的屬性進行具體的創建
本文的例子:ATestCompanyBuilder對象
導演類
對產品進行具體的組裝。
【具體的構建類】指的是產品中的屬性進行構建,
而該類是獲取最終的產品對象
本文的例子:Director對象
場景
代碼含義
沒有複雜業務,簡單代碼展示,對一個公司和員工的 bean 進行構建。
代碼展示
產品對象
公司對象
package com.builderpattern.vo;
import lombok.Data;
import java.util.List;
/**
* @version v1.0
* @Copyright(c): 2020-2020
* @FileName: Company.java
* @Description: 公司對象
* @autho Admin
* @date 2020/1/13 11:35
*/
@Data
public class Company {
/**
* 名稱
*/
private String name;
/**
* 公司統一社會信用代碼(公司的唯一標識)
*/
private String socialId;
/**
* 企業員工
*/
private List<CompanyPersonnel> companyPersonnelList;
}
公司員工對象
package com.builderpattern.vo;
import lombok.Data;
/**
* @version v1.0
* @Copyright(c): 2020-2020
* @FileName: CompanyPersonnel.java
* @Description:
* @autho Admin
* @date 2020/1/13 13:54
*/
@Data
public class CompanyPersonnel {
/**
* 員工姓名
*/
private String name;
/**
* 員工編號
*/
private String number;
/**
* 員工年齡
*/
private Integer age;
/**
* 員工性別 0:男 1:女
*/
private String sex;
}
抽象構建類
package com.builderpattern.build;
import com.builderpattern.vo.Company;
import com.builderpattern.vo.CompanyPersonnel;
import java.util.List;
/**
* @version v1.0
* @Copyright(c): 2020-2020
* @FileName: CompanyBuilder.java
* @Description:
* @autho Admin
* @date 2020/1/13 13:56
*/
public abstract class CompanyBuilder {
//創建公司對象(產品)
protected Company company = new Company();
/**
* 產品屬性建造 公司名稱 可以通過外部傳入獲取
* @return
*/
public abstract CompanyBuilder buildName(String name);
/**
* 產品屬性建造 統一社會信用代碼
* @return
*/
public abstract CompanyBuilder buildSocialId();
/**
* 產品屬性建造 公司員工集合
* @return
*/
public abstract CompanyBuilder buildPersonnelList();
/**
* 提供一個方法,可以得到產品
* @return
*/
public Company getCompany(){
return company;
}
}
具體的構建類
package com.builderpattern.build;
import com.builderpattern.vo.CompanyPersonnel;
import org.apache.commons.lang3.RandomUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @version v1.0
* @Copyright(c): 2020-2020
* @FileName: ATestCompanyBuilder.java
* @Description: A測試公司建造
* @autho Admin
* @date 2020/1/13 14:04
*/
public class ATestCompanyBuilder extends CompanyBuilder{
public CompanyBuilder buildName(String name) {
company.setName(name);
return this;
}
public CompanyBuilder buildSocialId() {
company.setSocialId("91123123213213211A");
return this;
}
public CompanyBuilder buildPersonnelList() {
ArrayList<CompanyPersonnel> list = new ArrayList<CompanyPersonnel>();
for (int i = 0; i < 10; i++) {
CompanyPersonnel companyPersonnel = new CompanyPersonnel();
companyPersonnel.setAge(18+i);
companyPersonnel.setName("測試員工"+(i+1));
companyPersonnel.setNumber(String.valueOf(i+1));
companyPersonnel.setSex(i%2==0?"0":"1");
list.add(companyPersonnel);
}
company.setCompanyPersonnelList(list);
return this;
}
}
導演類
package com.builderpattern.director;
import com.builderpattern.build.CompanyBuilder;
import com.builderpattern.vo.Company;
import lombok.Data;
/**
* @version v1.0
* @Copyright(c): 2020-2020
* @FileName: Director.java
* @Description:
* @autho Admin
* @date 2020/1/13 14:19
*/
@Data
public class Director {
//獲取build的基類對象,可以通過有參構造傳入
private CompanyBuilder companyBuilder;
public Director(CompanyBuilder companyBuilder){
this.companyBuilder = companyBuilder;
}
//負責公司(產品)對象的創建
public Company construct(String name){
return companyBuilder.buildName(name)
.buildPersonnelList()
.buildSocialId()
.getCompany();
}
}
測試類
package com.builderpattern;
import com.builderpattern.build.ATestCompanyBuilder;
import com.builderpattern.build.CompanyBuilder;
import com.builderpattern.director.Director;
import com.builderpattern.vo.Company;
/**
* @version v1.0
* @Copyright(c): 2020-2020
* @FileName: Test.java
* @Description:
* @autho Admin
* @date 2020/1/13 14:23
*/
public class Test {
public static void main(String[] args) {
//創建建造者
CompanyBuilder builder = new ATestCompanyBuilder();
//通過Director統一組建,並獲取產品
Director director = new Director(builder);
Company construct = director.construct("A測試公司");
System.out.println(construct);
}
}
測試結果
Company(name=A測試公司, socialId=91123123213213211A,
companyPersonnelList=
[CompanyPersonnel(name=測試員工1, number=1, age=18, sex=0),
CompanyPersonnel(name=測試員工2, number=2, age=19, sex=1),
CompanyPersonnel(name=測試員工3, number=3, age=20, sex=0),
CompanyPersonnel(name=測試員工4, number=4, age=21, sex=1),
CompanyPersonnel(name=測試員工5, number=5, age=22, sex=0),
CompanyPersonnel(name=測試員工6, number=6, age=23, sex=1),
CompanyPersonnel(name=測試員工7, number=7, age=24, sex=0),
CompanyPersonnel(name=測試員工8, number=8, age=25, sex=1),
CompanyPersonnel(name=測試員工9, number=9, age=26, sex=0),
CompanyPersonnel(name=測試員工10, number=10, age=27, sex=1)])
什麼時候使用
本文產品中的成員變量比較少,如果在業務比較複雜,成員變量很多,需要的有參構造方法比較多(而且可能有的成員變量要使用,有的不要使用,很容易亂。使用 set 多了,也會亂),難以維護,就可以使用該模式
附:目錄結構
有需要源碼的,也可以掃描下方二維碼,加我好友,私聊我
- END -
推薦閱讀
● 抽象工廠模式
● 裝飾者模式
● 工廠模式