介紹
定義
建造者模式是一種創(chuàng)建型模式铭段,它的定義如下
建造者模式(Builder Pattern) - 將一個復(fù)雜對象的構(gòu)建與它的表示分離蒲拉,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示
建造者模式是一步一步創(chuàng)建一個復(fù)雜的對象盒音,它允許用戶只通過指定復(fù)雜對象的類型和內(nèi)容就可以構(gòu)建它們侥袜,用戶不需要知道內(nèi)部的具體構(gòu)建細節(jié)舱权。又可以稱為生成器模式
適用場景
隔離復(fù)雜對象的創(chuàng)建和使用募胃,相同的方法旗唁,不同執(zhí)行順序,產(chǎn)生不同事件結(jié)果
多個部件都可以裝配到一個對象中痹束,但產(chǎn)生的運行結(jié)果不相同
產(chǎn)品類非常復(fù)雜或者產(chǎn)品類因為調(diào)用順序不同而產(chǎn)生不同作用
初始化一個對象時检疫,參數(shù)過多,或者很多參數(shù)具有默認值
Builder模式不適合創(chuàng)建差異性很大的產(chǎn)品類祷嘶。產(chǎn)品內(nèi)部變化復(fù)雜屎媳,會導(dǎo)致需要定義很多具體建造者類實現(xiàn)變化,增加項目中類的數(shù)量论巍,增加系統(tǒng)的理解難度和運行成本
需要生成的產(chǎn)品對象有復(fù)雜的內(nèi)部結(jié)構(gòu)烛谊,這些產(chǎn)品對象具備共性
建造者模式角色及類圖
建造者模式角色以及職責(zé)
- 產(chǎn)品類(Product):具體產(chǎn)品
- 抽象建造者(Builder):為創(chuàng)建一個Product產(chǎn)品對象的各個部件指定的抽象接口
- 具體建造者(ConcreteBuilder):具體建造者、實現(xiàn)Builder接口嘉汰,構(gòu)建和裝配各個部件
- 指揮者(Director):構(gòu)建一個使用Builder接口的對象
UML類圖
工廠模式和建造者模式的區(qū)別
構(gòu)建者模式和工廠模式很類似丹禀,區(qū)別在于構(gòu)建者模式是一種個性化產(chǎn)品的創(chuàng)建,通過組裝零配件而創(chuàng)建一個新產(chǎn)品鞋怀。而工廠模式是一種標(biāo)準化的產(chǎn)品創(chuàng)建双泪,不關(guān)心產(chǎn)品的構(gòu)建過程,只關(guān)心什么產(chǎn)品是由什么工廠產(chǎn)生的
實例
簡單實例
以一個點餐的過程為例密似,我們?nèi)サ娇觳偷暝芏粒總€人都可以根據(jù)自己的喜好自由搭配食物和飲料,最后生成的訂單也不盡相同辛友,如下
產(chǎn)品類
public class Meal {
private List<String> foods;
private List<String> drinks;
public Meal() {
this.foods = new ArrayList<>();
this.drinks = new ArrayList<>();
}
public List<String> getFoods() {
return foods;
}
public void setFoods(List<String> foods) {
this.foods = foods;
}
public List<String> getDrinks() {
return drinks;
}
public void setDrinks(List<String> drinks) {
this.drinks = drinks;
}
@Override
public String toString() {
return "Meal{" + "foods=" + foods + ", drinks=" + drinks + '}';
}
}
具體建造類
public class MealBuilder {
private Meal meal;
public MealBuilder() {
meal = new Meal();
}
public MealBuilder addFood(String foodName) {
meal.getFoods().add(foodName);
return this;
}
public MealBuilder addDrink(String drinkName) {
meal.getDrinks().add(drinkName);
return this;
}
public Meal build() {
return meal;
}
}
指揮者/測試
public class MealDirector {
@Test
public void test(){
MealBuilder mealBuilder = new MealBuilder();
// 組裝一個產(chǎn)品
Meal meal = mealBuilder.addFood("漢堡").addFood("雞肉卷").addDrink("可樂").build();
System.out.println(meal);
}
}
測試
Meal{foods=[漢堡, 雞肉卷], drinks=[可樂]}
模板方法模式擴展
上面的例子薄扁,在構(gòu)建實例的時候要我們按照需求動態(tài)的組裝零配件剪返,例如用餐的搭配組合。另外邓梅,我們也可以使用模板方法模式對建造者模式進行擴展脱盲,把零配件的組裝屏蔽封裝,例如我們在點餐的時候會有一些套餐日缨,這些套餐就是模板钱反,已經(jīng)幫我們搭配好零配件
抽象建造者
public abstract class AbstractMealBuilder {
protected Meal meal;
public AbstractMealBuilder() {
meal = new Meal();
}
public abstract void buildFood();
public abstract void buildDrink();
public Meal build() {
return meal;
}
}
具體建造者:A套餐
public class ConcreteMealBuilderA extends AbstractMealBuilder{
@Override
public void buildFood() {
meal.getFoods().add("辣雞堡");
meal.getFoods().add("雞肉卷");
}
@Override
public void buildDrink() {
meal.getDrinks().add("可樂");
}
}
具體建造者:B套餐
public class ConcreteMealBuilderB extends AbstractMealBuilder{
@Override
public void buildFood() {
meal.getFoods().add("牛肉堡");
meal.getFoods().add("薯條");
}
@Override
public void buildDrink() {
meal.getDrinks().add("橙汁");
}
}
指揮者
public class Director {
private AbstractMealBuilder mealBuilder;
public Director(AbstractMealBuilder mealBuilder) {
this.mealBuilder = mealBuilder;
}
public Meal construct() {
mealBuilder.buildFood();
mealBuilder.buildDrink();
return mealBuilder.build();
}
}
測試
public class DirectorDemo {
@Test
public void test() {
AbstractMealBuilder mealBuilderA = new ConcreteMealBuilderA();
Director directorA = new Director(mealBuilderA);
System.out.println("A套餐:" + directorA.construct());
AbstractMealBuilder mealBuilderB = new ConcreteMealBuilderB();
Director directorB = new Director(mealBuilderB);
System.out.println("B套餐:" + directorB.construct());
}
}
測試結(jié)果
A套餐:Meal{foods=[辣雞堡, 雞肉卷], drinks=[可樂]}
B套餐:Meal{foods=[牛肉堡, 薯條], drinks=[橙汁]}