設計模式之建造者模式

0x01.定義與類型

  • 定義:將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。
  • 用戶只需指定須要建造的類型就能夠獲得他們,建造過程及細節不須要知道
  • 類型:建立型
  • 實現建造模式的兩種方式

1.抽象建造者

  • UML:

抽象建造者模式

  • Java實現
/**
* 教練類,封裝了具體構建的細節
*/
public class Coach {

    private AProductBuilder productBuilder;

    public void setProductBuilder(AProductBuilder productBuilder) {
        this.productBuilder = productBuilder;
    }

    public Product createProduct(String property) {
        productBuilder.buildProperty(property);
        return this.productBuilder.makeProduct();
    }
}

/**
* 抽象的構建,每添加新的構建方式,只須要繼承這個抽象類便可
*/
public abstract class AProductBuilder {

    /**
    * 構建具體屬性,只是mock一個,能夠有不少個
    * @param property
    */
    abstract void buildProperty(String property);

    /**
    * 返回被構建的對象
    * @return
    */
    abstract Product makeProduct();
}

/**
* 產品具體的構建類
*/
public class ProductActualBuilder extends AProductBuilder {

    private Product product = new Product();

    @Override
    void buildProperty(String property) {
        product.setProperty(property);
    }

    @Override
    Product makeProduct() {
        return product;
    }
}

/**
* 產品類
*/
public class Product {

    /**
    * 產品實現細節,能夠不少個屬性,這裏只mock了一個
    */
    private String property;

    public void setProperty(String property) {
        this.property = property;
    }

    public String getProperty() {
        return property;
    }
}
  • 測試應用類
public class Test {

    public static void main(String[] args) {
        Coach coach = new Coach();
        coach.setProductBuilder(new ProductActualBuilder());
        Product product = coach.createProduct("測試屬性");
        System.out.println(product.getProperty());
    }
}
  • 輸出結果
測試屬性
  • 抽象建造者模式中的元素html

    • 產品類:通常是一個較爲複雜的對象,也就是說建立對象的過程比較複雜,通常會有比較多的代碼量。在本類圖中,產品類是一個具體的類,而非抽象類。實際編程中,產品類能夠是由一個抽象類與它的不一樣實現組成,也能夠是由多個抽象類與他們的實現組成。
    • 抽象建造者:引入抽象建造者的目的,是爲了將建造的具體過程交與它的子類來實現。這樣更容易擴展。通常至少會有兩個抽象方法,一個用來建造產品,一個是用來返回產品。
    • 建造者:實現抽象類的全部未實現的方法,具體來講通常是兩項任務:組建產品;返回組建好的產品。
    • 教練類:負責調用適當的建造者來組建產品,教練類通常不與產品類發生依賴關係,與教練類直接交互的是建造者類。通常來講,教練類被用來封裝程序中易變的部分。

2.使用靜態內部類和鏈式調用

  • UML:

靜態內部類鏈式建造者

  • Java實現
/**
* 產品類
*/
public class Product {
   /**
    * 產品屬性,只是舉了一個例子,能夠有不少個
    */
   private String property;

   /**
    * 產品的構建 構造方法
    * @param productBuilder
    */
   public Product (ProductBuilder productBuilder) {
       this.property = productBuilder.property;
   }

   public String getProperty() {
       return property;
   }

   public void setProperty(String property) {
       this.property = property;
   }

   /**
    * 產品構建類
    */
   public static class ProductBuilder {

       private String property;

       public ProductBuilder builderProperty (String property) {
           this.property = property;
           return this;
       }

       public Product build() {
           return new Product(this);
       }
   }
}
  • 輸出結果
測試屬性
  • 靜態內部類建造者模式的元素java

    • 產品:最終咱們須要的結果,較爲複雜或建立過程較爲複雜的對象。
    • 產品的構建類:builder類是整個建造者模式的核心,具體由兩項任務,一是構建產品細節,二是返回構建好的產品。

0x02.適用場景

  • 若是一個對象有很是複雜的內部結構(不少屬性),這個時候能夠考慮適用建造者模式。
  • 想把複雜對象的建立和使用分離的時候。

0x03.優勢

  • 封裝性好,建立和使用分離,使用建造者模式能夠有效的封裝變化,在使用建造者模式的場景中,通常產品類和建造者類是比較穩定的。
  • 擴展性好,建造類之間獨立,必定程度上解耦,若是有新的需求,經過實現一個新的建造者類就能夠完成,基本上不用修改以前已經測試經過的代碼,所以也就不會對原有功能引入風險。

0x04.缺點

  • 會產生多餘的Builder對象。
  • 產品內部發生變化,建造者都要修改,成本較大。

0x05.具體Java實現

  • 場景介紹:課程有課程名字,視頻,PPT和手記,舉例構建這個對象

1.抽象建造類的實現

  • 具體的實現
/**
* 課程教練類
*/
public class Coach {

    private CourseBuilder courseBuilder;

    public void setCourseBuilder(CourseBuilder courseBuilder) {
        this.courseBuilder = courseBuilder;
    }

    public Course makeCourse(String courseName,
                            String coursePPT,
                            String courseVideo,
                            String courseArticle,
                            String courseQA) {
        this.courseBuilder.buildCourseName(courseName);
        this.courseBuilder.buildCoursePPT(coursePPT);
        this.courseBuilder.buildCourseArticle(courseArticle);
        this.courseBuilder.buildCourseVideo(courseVideo);
        this.courseBuilder.buildCourseQA(courseQA);
        return this.courseBuilder.makeCourse();
    }
}

/**
* 建造者的具體實現與應用
*/
public abstract class CourseBuilder {

    public abstract void buildCourseName(String courseName);

    public abstract void buildCoursePPT(String coursePPT);

    public abstract void buildCourseVideo(String courseVideo);

    public abstract void buildCourseArticle(String courseArticle);

    public abstract void buildCourseQA(String courseQA);

    public abstract Course makeCourse();
}


/**
* 建造者的具體實現
*/
public class CourseActualBuilder extends CourseBuilder {

    private Course course = new Course();

    @Override
    public void buildCourseName(String courseName) {
        course.setCourseName(courseName);
    }

    @Override
    public void buildCoursePPT(String coursePPT) {
        course.setCoursePPT(coursePPT);
    }

    @Override
    public void buildCourseVideo(String courseVideo) {
        course.setCourseVideo(courseVideo);
    }

    @Override
    public void buildCourseArticle(String courseArticle) {
        course.setCourseArticle(courseArticle);
    }

    @Override
    public void buildCourseQA(String courseQA) {
        course.setCourseQA(courseQA);
    }

    @Override
    public Course makeCourse() {
        return course;
    }
}

/**
* 具體產品的實例:課程
*/
public class Course {

    private String courseName;

    private String coursePPT;

    private String courseVideo;

    private String courseArticle;

    //question & answer
    private String courseQA;

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public String getCoursePPT() {
        return coursePPT;
    }

    public void setCoursePPT(String coursePPT) {
        this.coursePPT = coursePPT;
    }

    public String getCourseVideo() {
        return courseVideo;
    }

    public void setCourseVideo(String courseVideo) {
        this.courseVideo = courseVideo;
    }

    public String getCourseArticle() {
        return courseArticle;
    }

    public void setCourseArticle(String courseArticle) {
        this.courseArticle = courseArticle;
    }

    public String getCourseQA() {
        return courseQA;
    }

    public void setCourseQA(String courseQA) {
        this.courseQA = courseQA;
    }

    @Override
    public String toString() {
        return "Course{" +
                "courseName='" + courseName + '\'' +
                ", coursePPT='" + coursePPT + '\'' +
                ", courseVideo='" + courseVideo + '\'' +
                ", courseArticle='" + courseArticle + '\'' +
                ", courseQA='" + courseQA + '\'' +
                '}';
    }
}
  • 測試與應用
/**
* 測試與應用
*/
public class Test {
    public static void main(String[] args) {
        CourseBuilder courseBuilder = new CourseActualBuilder();

        Coach coach = new Coach();
        coach.setCourseBuilder(courseBuilder);

        Course course = coach.makeCourse(
                "Java設計模式精講",
                "Java設計模式精講PPT",
                "Java設計模式精講視頻",
                "Java設計模式精講手記",
                "Java設計模式精講問答"
                );

        System.out.println(course);
    }
}
  • 輸出結果
Course{courseName='Java設計模式精講', coursePPT='Java設計模式精講PPT', courseVideo='Java設計模式精講視頻', courseArticle='Java設計模式精講手記', courseQA='Java設計模式精講問答'}
  • UML類圖

抽象建造者課程實例UML圖

2.靜態內部類建造者模式

  • 具體的實現
/**
 * 課程類
 */
public class Course {

    private String courseName;

    private String coursePPT;

    private String courseVideo;

    private String courseArticle;

    //question & answer
    private String courseQA;

    public Course(CourseBuilder courseBuilder) {
        this.courseName = courseBuilder.courseName;
        this.courseArticle = courseBuilder.courseArticle;
        this.coursePPT = courseBuilder.coursePPT;
        this.courseVideo = courseBuilder.courseVideo;
        this.courseQA = courseBuilder.courseQA;
    }

    @Override
    public String toString() {
        return "Course{" +
                "courseName='" + courseName + '\'' +
                ", coursePPT='" + coursePPT + '\'' +
                ", courseVideo='" + courseVideo + '\'' +
                ", courseArticle='" + courseArticle + '\'' +
                ", courseQA='" + courseQA + '\'' +
                '}';
    }

    /**
     * 課程靜態builder類
     */
    public static class CourseBuilder {

        private String courseName;

        private String coursePPT;

        private String courseVideo;

        private String courseArticle;

        //question & answer
        private String courseQA;



        public CourseBuilder buildCourseName(String courseName) {
            this.courseName = courseName;
            return this;
        }

        public CourseBuilder buildCoursePPT(String coursePPT) {
            this.coursePPT = coursePPT;
            return this;
        }

        public CourseBuilder buildCourseVideo(String courseVideo) {
            this.courseVideo = courseVideo;
            return this;
        }

        public CourseBuilder buildCourseArticle(String courseArticle) {
            this.courseArticle = courseArticle;
            return this;
        }

        public CourseBuilder buildCourseQA(String courseQA) {
            this.courseQA = courseQA;
            return this;
        }

        public Course build() {
            return new Course(this);
        }
    }
}
  • 測試與應用
/**
 * 測試與應用
 */
public class Test {
    public static void main(String[] args) {
        Course course1 = new Course.CourseBuilder()
                .buildCourseName("Java課程精講")
                .buildCourseArticle("Java課程精講手機")
                .buildCoursePPT("Java課程精講PPT")
                .buildCourseVideo("Java課程精講視頻")
                .build();

        System.out.println(course1.toString());

        Course course2 = new Course.CourseBuilder()
                .buildCourseName("Java課程精講")
                .buildCourseVideo("Java課程精講視頻")
                .build();

        System.out.println(course2.toString());
    }
}
  • 輸出結果
Course{courseName='Java課程精講', coursePPT='Java課程精講PPT', courseVideo='Java課程精講視頻', courseArticle='Java課程精講手機', courseQA='null'}
Course{courseName='Java課程精講', coursePPT='null', courseVideo='Java課程精講視頻', courseArticle='null', courseQA='null'}
  • UML

靜態內部類建造者鏈式調用建造者模式課程實例

0x06.建造者和工廠對比

  • 建造者和工廠模式都屬於建立類的設計模式,自己的場景很類似。
  • 建造者:注重方法的調用順序,建造複雜的產品,由不少複雜的部件組成,不止建立產品還要知道產品的組成。
  • 工廠:注重產品,產品基本都是一個樣子,只是生產產品,不關心產品組成。

0x07.源碼中的建造者模式

  • StringBuilder
  • StringBuffer
  • Guava: ImtableSet
  • CacheBuilder
  • Spring: BeanDefinitionBuilder
  • MyBatis: SqlSessionFactoryBuilder

0x08.樣例代碼

建造者模式https://github.com/sigmako/design-pattern/tree/master/buildergit

0x09.參考

相關文章
相關標籤/搜索