建造者模式

1.模式簡介

      建造者模式(Builder Pattern)屬於建立型模式中的一種,在建立比較複雜的對象,或者對象包含多個組成部分時比較有用,用於將對象的建立過程與使用分離,隔離具體的建立細節,方便之後的擴展。它的使用場景包括:設計模式

  • 對象的建立比較複雜,須要進行許多處理工做
  • 對象包含多個組成部分,而這幾個部分之間經常會有較爲固定的順序
  • 建立對象須要許多參數,會致使構建時的參數列表過長,難以理解和維護

      本文將以一個具體的例子做爲引子,經過對比的形式講解建造者模式的優勢,最後引入定義和類圖。ide

2.案例分析

      這裏以作菜爲例子,一般作菜的步驟包括:放油,放蔥薑蒜,加肉,翻炒,加鹽,繼續翻炒,裝盤,那麼作一份豆角炒肉代碼能夠這樣寫:ui

public class SimpleCook {
  public static void main(String[] args) {
    SimpleCook cook = new SimpleCook();
    cook.cookmeatWithBeans();
  }

  public void cookmeatWithBeans(){
    System.out.println("熱鍋下油。。。");
    System.out.println("加肉。。。");
    System.out.println("加入蔥薑蒜。。。");
    System.out.println("放入豆角。。。");
    System.out.println("翻炒均勻。。。");
    System.out.println("加鹽,繼續翻炒。。。");
    System.out.println("出鍋。。。");
  }
}

      OK,一盤香噴噴的豆角炒肉就作好了。不過,上面的代碼還有一些問題:①代碼將每一個步驟一筆帶過,實際上每一步都會有許多細節,好比第一步下油,何時倒油,倒多少合適?若是把這些詳細步驟所有寫在一塊兒,各個步驟之間不只耦合嚴重,並且代碼還會顯得雜亂,一旦某個步驟須要改善,整個方法都受影響;②擴展性問題,若是我想換個藕丁炒肉,那就須要新添加一個方法,沒有擴展性。並且咱們會發現豆角炒肉和藕丁炒肉全部的步驟都同樣,只是把「放入豆角」改爲了「放入藕丁」,隨着類型菜品的增多,系統會充斥大量的冗餘代碼。this

      所以,這裏須要將每一個步驟單獨提出來做爲一個方法,炒菜的步驟修改以後以下:spa

public class SimpleCook {
  public static void main(String[] args) {
    SimpleCook cook = new SimpleCook();
    cook.cookMeatWithBeansBetterWay();
  }

  public void cookMeatWithBeansBetterWay(){
    addOil();
    addMeat();
    addIngredients();
    addDish();
    cookForAWhile();
    addSalt();
    finish();
  }

  private void finish() {
    System.out.println("出鍋。。。");
  }

  private void addSalt() {
    System.out.println("加鹽,繼續翻炒。。。");
  }

  private void cookForAWhile() {
    System.out.println("翻炒均勻。。。");
  }

  private void addDish() {
    System.out.println("放入豆角。。。");
  }

  private void addIngredients() {
    System.out.println("加入蔥薑蒜。。。");
  }

  private void addMeat() {
    System.out.println("加肉。。。");
  }

  private void addOil() {
    System.out.println("熱鍋下油。。。");
  }
}

      因爲不少菜品都遵循相似的步驟,只是具體實現不同,那麼就能夠抽象出一個父類,而後具體的步驟交給子類去實現,對於其中共同的部分,能夠在抽象父類中提供默認實現:設計

public abstract class Builder {
  public abstract void addOil();
  public abstract void addMeat();
  public abstract void addIngredients();
  public abstract void addDish();
  public void cookForAWhile(){
    System.out.println("翻炒均勻。。。");
  }
  public abstract void addSalt();
  public void finish(){
    System.out.println("出鍋。。。");
  }
}

      抽象父類提供了兩個方法的默認實現,其餘的交給子類去處理,下面是藕丁炒肉子類的實現,豆角炒肉與此相似:3d

public class MeatWithLotusRootBuilder extends Builder{

  @Override
  public void addOil() {
    System.out.println("熱鍋下油。。。");
  }

  @Override
  public void addMeat() {
    System.out.println("加肉。。。");
  }

  @Override
  public void addIngredients() {
    System.out.println("加入蔥薑蒜。。。");
  }

  @Override
  public void addDish() {
    System.out.println("放入藕丁。。。");
  }

  @Override
  public void addSalt() {
    System.out.println("加鹽,繼續翻炒。。。");
  }
}

      如今,就能夠按照開始規定的步驟炒菜了,這裏,咱們將炒菜的流程放在Director中,由該類管理具體的步驟順序:code

public class Director {
  Builder builder;

  public Director(Builder builder){
    this.builder = builder;
  }

  public void cook(){
    builder.addOil();
    builder.addIngredients();
    builder.addMeat();
    builder.addDish();
    builder.cookForAWhile();
    builder.addSalt();
    builder.finish();
  }
}

      當咱們須要點餐時,只須要告訴Director菜品的名字就能夠了,菜就會按照流程作出來:對象

// 客戶端代碼
public class BuilderCook {
  public static void main(String[] args) {
    Builder builder = new MeatWithLotusRootBuilder();
    Director director = new Director(builder);
    director.cook();
  }
}

      輸出爲:blog

熱鍋下油。。。
加入蔥薑蒜。。。
加肉。。。
放入藕丁。。。
翻炒均勻。。。
加鹽,繼續翻炒。。。
出鍋。。。

      相比最開始的炒菜方法,改進以後增長了Director、Builder、Builder子類,Director類規定了建立對象的順序,Builder抽象了炒菜的通常步驟,Builder子類則對應每種菜品的具體實現。

3. 模式類圖與定義

      根據上面的代碼,總結出建造者模式的類結構以下:

      其通常定義爲:

建造者模式:將一個複雜對象的構建與它的表示相分離,使得一樣的構建過程能夠建立不一樣的表示。

 4. 常見用法

      工做中,建造者模式更常見的使用場景是對象要設置的參數過多的狀況,例如,將人抽象爲一個Person類,建立的時候須要傳遞許多信息,可使用各類setter方法,可是Builder模式可以讓這種寫法更優雅,代碼以下:

public class Person {
  String name;
  int age;
  double height;
  double weight;
  String sex;
  //省略其餘字段

  public static void main(String[] args) {
    Person person =
      new Builder().name("zhang san")
        .age(20).height(174)
        .weight(130)
        .sex("male")
        .build();
  }

  public Person(Builder builder){
    this.age = builder.age;
    this.height = builder.height;
    this.weight = builder.weight;
    this.name = builder.name;
    this.sex = builder.sex;
  }

  public static class Builder{
    String name;
    int age;
    double height;
    double weight;
    String sex;

    public Builder age(int age){
      this.age = age;
      return this;
    }

    public Builder height(double height){
      this.height = height;
      return this;
    }

    public Builder weight(double weight){
      this.weight = weight;
      return this;
    }

    public Builder name(String name){
      this.name = name;
      return this;
    }

    public Builder sex(String sex){
      this.sex = sex;
      return this;
    }

    public Person build(){
      return new Person(this);
    }
  }
}

5. 參考

<<大話設計模式>>

一篇文章就完全弄懂建造者模式(Builder Pattern)

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息