設計模式之-創建類模式大PK

2019-11-03     Java架構人生
  • 創建類模式包括工廠方法模式、建造者模式、抽象工廠模式、單例模式和原型模式,他們能夠提供對象的創建和管理職責。其中單例模式和原型模式模式非常容易理解,單例模式是要保持在內存中只有一個對象,原型模式是通過複製的方式產生一個新的對象。而工廠方法模式、抽象工廠模式和建造者模式,這三者之間有較大的相似性。

工廠方法模式VS建造者模式

  • 工廠方法模式注重的是整體對象的創建方法,而建造者模式注重的是部件構建的過程,旨在通過一步一步地精確構造創建出一個複雜的對象。就拿造車來說吧,工廠方法模式,直接生產出來的就是奔馳、寶馬和大眾;而建造者模式則不同了,則需要創建車胎、引擎、車門、座椅、車燈等等,然後組裝成一輛奔馳或者寶馬車。如下我們分別介紹兩種模式的造車過程。
  • 工廠方法模式造車

首先工廠方法模式的類圖如下,其中我們將車輛分為三種奔馳、寶馬、大眾,定義一個接口,在定義三種車型的創建實現,通過汽車製造工廠生產汽車。通過類圖代碼略。

  • 建造者模式造車

建造者模式設計一個車需要先把車進行拆分,分為引擎、車輪和車體三部分,然後由建造者進行建造,並通過設計圖紙建造車輛,注重零件的配合、組裝和封裝從一個細微構件角度看待一個對象,建造者模式的類圖如下。



這個看起來還有點複雜呢,我們還是看看通用類圖的源碼吧,一點一點的分析一下,首先我們還是先看看這個奔馳和寶馬汽車吧,還是把大眾汽車給忘記了!源碼還是挺簡單的,就是一些get和set方法。

public interface ICar {
public String getWheel();
public String getEngine();
public String getCarbody();
}
public class Benz implements ICar{
private Blueprint bp;
public Benz(Blueprint bp){
this.bp = bp;
}
@Override
public String getWheel() {
// TODO Auto-generated method stub
return this.bp.getWheel();
}
@Override
public String getEngine() {
// TODO Auto-generated method stub
return this.bp.getEngine();
}
@Override
public String getCarbody() {
// TODO Auto-generated method stub
return this.bp.getBody();
}
}
public class BMW implements ICar{
private Blueprint bp;
public BMW(Blueprint bp){
this.bp = bp;
}
public String getBody() {
return this.bp.getBody();
}
public String getWheel() {
// TODO Auto-generated method stub
return this.bp.getWheel();
}
@Override
public String getEngine() {
// TODO Auto-generated method stub
return this.bp.getEngine();
}
@Override
public String getCarbody() {
// TODO Auto-generated method stub
return this.bp.getBody();
}
}

接下來我們看看我們重頭戲CarBuilder,寫起來發現也沒有那麼複雜了。

public abstract class CarBuilder {
private Blueprint bp;
public abstract ICar buildCar();
public void receiveBlueprint(Blueprint bp){
this.bp = bp;
}
protected Blueprint getBlueprint(){
return this.bp;
}
}
public class BenzBuilder extends CarBuilder{
@Override
public ICar buildCar() {
// TODO Auto-generated method stub
return new Benz(super.getBlueprint());
}
}
public class BMWBuilder extends CarBuilder{
@Override
public ICar buildCar() {
// TODO Auto-generated method stub
return new BMW(super.getBlueprint());
}
}

最後只剩下導演類了,看來最複雜的還是導演,要設計車輛的藍圖,並正確的調用建造方法。

public class Director {
private CarBuilder benzBuilder = new BenzBuilder();
private CarBuilder BMWbuilder = new BMWBuilder();
private Blueprint bp;
public ICar createBenz(){
bp = new Blueprint();
bp.setBody("BenzBody");
bp.setEngine("BenzEngine");
bp.setWheel("BenzWheel");
return createCar(benzBuilder, bp);
}
public ICar createBMW(){
bp = new Blueprint();
bp.setBody("BMWBody");
bp.setEngine("BMWEngine");
bp.setWheel("BMWWheel");
return createCar(BMWbuilder, bp);
}
private ICar createCar(CarBuilder carBuilder, Blueprint bp){
carBuilder.receiveBlueprint(bp);
return carBuilder.buildCar();
}
}

大功告成,我們通過客戶端調用一下看看運行狀況。

public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Director director = new Director();
ICar benz = director.createBenz();
ICar BMW = director.createBMW();
System.out.println(benz.getCarbody()); //BenzBody
System.out.println(BMW.getCarbody()); //BMWBody
}
}
  • 最佳實踐

工廠方法模式和建造者模式都屬於對象創建類模式,都是用來創建類對象。但他們之間區別還是比較明顯的。

  • 意圖不同:工廠方法模式關注的是產品的整體,如寶馬、大眾車整體,無需關心產品的各個部分是如何創建出來的;但在建造者模式中,一個具體產品的產生是依賴各個部件的產生以及裝配順序,它關注的是「由零件一步一步地組裝出產品對象」。工廠方法模式創建對象粒度較粗,而建造者模式創建對象的粒度較細。
  • 產品的複雜度不同,工廠方法模式創建出來的寶馬和奔馳車的樣子是一樣的,而建造者模式創建的寶馬車和奔馳車可以分別指定不同的車體部分。

抽象工廠模式VS建造者模式

抽象工廠模式實現對產品家族的創建,一個產品家族是一系列不同分類維度的產品組合,採用抽象工廠模式則是不需要關心構建過程,只關心什麼產品由什麼工廠生產即可。我們生產的奔馳和寶馬車當然不能各只有一種型號,奔馳車有商務車還有運動型車SUV,同樣寶馬車也是如此。因此我們需要改進工廠方法模式,引入抽象工廠模式生產車輛。抽象工廠模式類圖如下:

對外界調用者來說,只要更換了一個具備相同結構的對象,即可發生非常大的改變,如我們原本使用BenzFactory生產汽車,但是系統突然也生產寶馬汽車,則只需要將BenzFactory替換為BMWFactory即可,注意這裡生產的是一輛完整的車,對於一個產品,只要給出產品的代碼即可生產,抽象工廠模式把一輛車認為是一個完整的,不可拆分的對象,注重完整性,不會出現一個寶馬工廠生產奔馳車的情況,不能生產混合車型。而建造者模式可以將不同車型的零件任意組合。如果希望屏蔽對象的創建過程,只提供一個封裝良好的對象,則可以選擇抽象工廠模式。而建造者模式可以用在構件的裝配方面,如通過裝配不同的組件或者相同組件的不同順序,可以產生出一個新的對象,是一個非常靈活的架構,方便地擴展和維護系統。

文章來源: https://twgreatdaily.com/SkWML24BMH2_cNUg28QO.html