1. 程式人生 > >Java Builder 模式,你搞明白了麼?

Java Builder 模式,你搞明白了麼?

Builder 模式定義

Builder 模式中文叫作建造者模式,又叫生成器模式,它屬於物件建立型模式,是將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。建造者模式是一步一步建立一個複雜的物件,它允許使用者只通過指定複雜物件的型別和內容就可以構建它們,使用者不需要知道內部的具體構建細節。下圖是建造者模式的通用類圖:

在建造者模式中,有如下4種角色:

  • Product:產品角色
  • Builder:抽象建造者,定義產品介面
  • ConcreteBuilder:具體建造者,實現Builder定義的介面,並且返回組裝好的產品
  • Director:指揮者,屬於這裡面的老大,你需要生產什麼產品都直接找它。

建造者模式應用舉例

家裝

家裝不管是精裝還是簡裝,它的流程都相對固定,所以它適用於建造者模式。我們就以家裝為例,一起來學習瞭解一下建造者模式。下圖是家裝建造者模式簡單的 UML 圖。

1、家裝物件類

/**
 * 家裝物件類
 */
public class House {
    // 買家電
    private String jiadian;

    // 買地板
    private String diban;
    // 買油漆
    private String youqi;

    public String getJiadian() {
        return jiadian;
    }

    public void setJiadian(String jiadian) {
        this.jiadian = jiadian;
    }

    public String getDiban() {
        return diban;
    }

    public void setDiban(String diban) {
        this.diban = diban;
    }

    public String getYouqi() {
        return youqi;
    }

    public void setYouqi(String youqi) {
        this.youqi = youqi;
    }

    @Override
    public String toString() {
        return "House{" +
                "jiadian='" + jiadian + '\'' +
                ", diban='" + diban + '\'' +
                ", youqi='" + youqi + '\'' +
                '}';
    }
}

2、抽象建造者 Builder 類

/**
 * 抽象建造者
 */
public interface HouseBuilder {
    // 買家電
    void doJiadian();
    // 買地板
    void doDiBan();
    // 買油漆
    void doYouqi();

    House getHouse();
}

3、具體建造者-簡裝建造者類

/**
 * 簡裝建立者
 */
public class JianzhuangBuilder implements HouseBuilder {

    private House house = new House();

    @Override
    public void doJiadian() {
        house.setJiadian("簡單家電就好");
    }

    @Override
    public void doDiBan() {
        house.setDiban("普通地板");
    }

    @Override
    public void doYouqi() {
        house.setYouqi("汙染較小的油漆就行");
    }

    @Override
    public House getHouse() {
        return house;
    }
}

4、具體建造者-精裝建造者類

/**
 * 精裝建立者
 */
public class jingzhuangBuilder implements HouseBuilder {

    private House house = new House();

    @Override
    public void doJiadian() {
        house.setJiadian("二話不說,最好的");
    }

    @Override
    public void doDiBan() {
        house.setDiban("二話不說,實木地板");
    }

    @Override
    public void doYouqi() {
        house.setYouqi("二話不說,給我來0汙染的");
    }

    @Override
    public House getHouse() {
        return house;
    }
}

5、指揮官-家裝公司類

/**
 * 家裝公司,值需要告訴他精裝還是簡裝
 */
public class HouseDirector {

    public House builder(HouseBuilder houseBuilder){
        houseBuilder.doDiBan();
        houseBuilder.doJiadian();
        houseBuilder.doYouqi();
        return houseBuilder.getHouse();
    }
}

6、測試

public class App {
    public static void main(String[] args) {
        house();
    }

    public static void house(){
        HouseDirector houseDirector = new HouseDirector();
        // 簡裝
        JianzhuangBuilder jianzhuangBuilder = new JianzhuangBuilder();
        System.out.println("我要簡裝");
        System.out.println(houseDirector.builder(jianzhuangBuilder));

        // 精裝
        jingzhuangBuilder jingzhuangBuilder = new jingzhuangBuilder();
        System.out.println("我要精裝");
        System.out.println(houseDirector.builder(jingzhuangBuilder));

    }
}

輸出結果

我們以家裝為例,實現了兩個具體的建造者,一個簡裝建造者、一個精裝建造者。我們只需要告訴家裝公司,我是需要簡裝還是精裝,他會去幫我們安排,我不需要知道里面具體的細節。怎麼樣,建造者模式學回了嗎?

物件構建

在日常開發中,你是不是會經常看到下面這種程式碼:


return new Docket(DocumentationType.SWAGGER_2)
        .apiInfo(apiInfo())
        .select()
        .apis(RequestHandlerSelectors.basePackage("com.curry.springbootswagger.controller"))
        .paths(PathSelectors.any())
        .build();

是不是很優美?學會了 Builder 模式之後,你也可以通過這種方式進行物件構建。它是通過變種的 Builder 模式實現的。先不解釋了,我們先用 Builder 模式來實現跟上述的物件構建,使用學生類為例。

學生物件程式碼:

public class Student {

    private String name;

    private int age;

    private int num;

    private String email;

    // 提供一個靜態builder方法
    public static Student.Builder builder() {
        return new Student.Builder();
    }
    // 外部呼叫builder類的屬性介面進行設值。
    public static class Builder{
        private String name;

        private int age;

        private int num;

        private String email;

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

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

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

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

        public Student build() {
            // 將builder物件傳入到學生建構函式
            return new Student(this);
        }
    }
    // 私有化構造器
    private Student(Builder builder) {
        name = builder.name;
        age = builder.age;
        num = builder.num;
        email = builder.email;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", num=" + num +
                ", email='" + email + '\'' +
                '}';
    }
}

呼叫程式碼:

    public static void student(){
        Student student = Student.builder().name("平頭哥").num(1).age(18).email("平頭哥@163.com").build();
        System.out.println(student);
    }

可以看到,變種 Builder 模式包括以下內容:

  • 在要構建的類內部建立一個靜態內部類 Builder
  • 靜態內部類的引數與構建類一致
  • 構建類的構造引數是 靜態內部類,使用靜態內部類的變數一一賦值給構建類
  • 靜態內部類提供引數的 setter 方法,並且返回值是當前 Builder 物件
  • 最終提供一個 build 方法構建一個構建類的物件,引數是當前 Builder 物件

可能你會說,這種寫法實現太麻煩了,確實需要我們寫很多額外的程式碼,好在前輩們已經開發出了lombok來拯救我們,我們只需要引入lombok外掛,然後在實體類上新增@Builder註解,你就可以實用 Builder 模式構建物件了。

建造者模式的優缺點

優點

  • 在建造者模式中, 客戶端不必知道產品內部組成的細節,將產品本身與產品的建立過程解耦,使得相同的建立過程可以建立不同的產品物件
  • 每一個具體建造者都相對獨立,而與其他的具體建造者無關,因此可以很方便地替換具體建造者或增加新的具體建造者, 使用者使用不同的具體建造者即可得到不同的產品物件
  • 可以更加精細地控制產品的建立過程 。將複雜產品的建立步驟分解在不同的方法中,使得建立過程更加清晰,也更方便使用程式來控制建立過程
  • 增加新的具體建造者無須修改原有類庫的程式碼,指揮者類針對抽象建造者類程式設計,系統擴充套件方便,符合“開閉原則”

缺點

  • 建造者模式所建立的產品一般具有較多的共同點,其組成部分相似,如果產品之間的差異性很大,則不適合使用建造者模式,因此其使用範圍受到一定的限制。
  • 如果產品的內部變化複雜,可能會導致需要定義很多具體建造者類來實現這種變化,導致系統變得很龐大。

文章不足之處,望大家多多指點,共同學習,共同進步

最後

打個小廣告,歡迎掃碼關注微信公眾號:「平頭哥的技術博文」,一起進步吧。

相關推薦

Java Builder 模式,明白

Builder 模式定義 Builder 模式中文叫作建造者模式,又叫生成器模式,它屬於物件建立型模式,是將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。建造者模式是一步一步建立一個複雜的物件,它允許使用者只通過指定複雜物件的型別和內容就可以構建它們,使用者不需要知道內部的具體構建細

Java Builder 模式,?

加油.png 前言:最近閒來無事的時候想著看看一些平常用的三方庫原始碼,沒想到看了之後才知道直接擼原始碼好傷身體,一般設計優秀的開源庫都會涉及很多的設計模式,就比如 android 開發使用頻繁的 okHttp 開啟原始碼一看,納尼?Builder 模式隨處可見,

Java培訓,要英語基礎嗎?看明白

有人問這樣的問題:英語成績差可以學Java嗎?英語不好影響Java學習嗎?到睿峰諮詢Java課程的同學也常常有這樣的擔憂,經常有人問到成都Java培訓機構學習要英語基礎嗎?今天就告訴大家答案。 到成都Java培訓機構學習要英語基礎嗎?答案是肯定的,每個人的心裡也是明白的,畢竟所有的程式設計程式碼都是由英語單

[轉帖]USB-C和Thunderbolt 3連線線嗎?---沒明白.

USB-C和Thunderbolt 3連線線你搞懂了嗎? 2018年11月25日 07:30  6318 次閱讀 稿源:威鋒網 3 條評論 按照計算行業的風潮,USB Type-C 將會是下一代主流的介面。不過,

C語言/原子/編譯,真的明白嗎?

clas done ati pre 內存 程序 導致 裏的 creat   說到原子,類似於以下的代碼可能人人都可以看出貓膩。 #include <stdio.h> #include <pthread.h> int cnt = 0;

不懂卷積神經網路?別怕,看完這幾張萌圖明白

這篇文章用最簡明易懂的方式解釋了卷積神經網路(CNN)的基本原理,並繞開了裡面的數學理論。 同時,如果想對從頭開始構建CNN網路之類的問題感興趣,作者推薦去讀《 Artificial Intelligence for Humans Volume 3: Deep Learning and Neur

Java Builder模式 Lambda表示式 Java8 lambda表示式10個示例

Java Builder模式 package com.cathay;/** * @Description * @TODO * @Author [email protected] * @Date 建立時間:2018/11/16 **/public class Person { private

Java面試題-阿里、餓、鏈家、攜程

一、J2SE部分 1、Java基礎 ==與equals()方法的區別? 1. ==在比較基本資料型別時比較的是值,比較兩個物件時比較的是地址值; 2. equals()方法存在於Object類中,Object類中equals()方法底層依賴的是==操作, 在所有沒

電腦錄屏桌面哪個軟體好?看完明白

    首先一說到電腦桌面錄屏這個東西,我知道大家都不陌生,但是我想說的是你們在用過這麼多的軟體之後有什麼認為好用的錄屏軟體嗎?之前就會有寶寶們問我關於這方面的知識,但是由於小編沒有自己親身試驗過所以不敢輕易向大家推薦,今天寫這邊文章的目的就是來回答之前寶寶們的疑問的,如果感興趣的寶寶

資料庫的隔離級別,真的理解

本篇講訴資料庫中事務的四大特性(ACID),並且將會詳細地說明事務的隔離級別。如果一個數據庫聲稱支援事務的操作,那麼該資料庫必須要具備以下四個特性: ⑴ 原子性(Atomicity)   原子性是指事務包含的所有操作要麼全部成功,要麼全部失敗回滾,這和前面兩篇部落格介紹事務的功能是一樣的概念

erp系統為什麼要選穩定性強的?看完明白

隨著社會生產力的發展,企業對資訊化管理需求也迅速增強,如此形勢之下,紛紛開啟了尋求erp管理系統的旅程,面對市場上大量湧現的ERP軟體,企業該如何選擇呢?下面小編就為大家分享一些選擇ERP系統的建議和方法,希望對大家能有所幫助。選擇ERP管理系統需考慮三大要素: 一、首先要立足自身業務,隨著行業的不斷細分,

erp系統為什麽要選穩定性強的?看完明白

之一 企業 發揮 最有 努力 如何選擇 erp系統 過程 快速 隨著社會生產力的發展,企業對信息化管理需求也迅速增強,如此形勢之下,紛紛開啟了尋求erp管理系統的旅程,面對市場上大量湧現的ERP軟件,企業該如何選擇呢?下面小編就為大家分享一些選擇ERP系統的建議和方法,希望

Java Builder模式的寫法和lombok外掛@Builder註解的支援

1. Builder模式簡化get set方法,只需要定義一個靜態公共的內部類即可 public class User { private Integer id; private Str

裝修不會算賬?沒關係,看完吉材易達裝修輔材的介紹明白

對初次裝修的業主來說,裝修是件繁瑣複雜的大事。因為不同於快消品的一次性消費,使得業主們普遍對新房裝修十分關注與投入。然而儘管業主精力和感情上都十分投入,但因為是外行,所以在裝修中總會出現種種的不如人意。不少業主在裝修後表示對全過程的後悔。無論在資金投入上還是裝修

Verification 3.0 準備好

來源:路科驗證;原創:張石 Jim Hogan,Vista Ventures和LLC的執行合夥人jimHogan也是EDA領域資深的投資者,最近一直在關注一些驗證初創公司,包括雲技術公司-Metrics以及行動式激勵(portable stimulus)的先驅Breker Verificatio

Python程式設計師的辛酸,第三個我服,第九個看懂

聚焦廣大碼農 感悟程式設計師資訊 大家好,小編今天和大家分享咱們程式設計師的辛酸經歷 有多少程式設計師整天在於BUG奮鬥呢?有多少程式設計師沒有時間解決自己的個人情感問題?又有多少程式設計師在工作中艱苦奮鬥,工作後和專案經理鬥智鬥勇?下面下邊給大家介紹咱們程式設計師的辛酸經歷,不知道你有

java之foreach,判null嗎?

從jdk1.5之後,Java提供了foreach用於遍歷集合、陣列等。但是我在工作中,經常發現大家在使用foreach時,經常會忘記判斷集合是否為null。下面我們舉個簡單的例子: //常見的從資料庫查詢到的資料集合 List<String> dataLi

運動過度?

       只見他一直生龍活虎的進行體育鍛煉,並且總是滿負荷運轉,運動起來像個“瘋子”一般。曾經有一段時間,可能會發現鍛鍊的效果確實不錯,因為自己的力氣在增加,耐力在增強,脂肪在減少,一切都進展得非常順利。然而,好景不長,某天早晨醒來後,忽然感到倦怠乏力,渾身不適,從此這種感覺便如幽靈般一直揮之不去

常坐電腦前面,這些健康問題注意到

【伯樂線上導讀】:本文要討論的健康問題,其實並不僅僅限於程式設計師,其他那些需要長期坐在電腦前的工作,比如:網路編輯、網站管理員、IT 從業人員等,也會面臨同樣的健康問題。本文目的就是要讓業界的朋友們對自己面臨的健康問題引起關注。 Zed Shaw,程式設計師,吉他

C++變數的宣告和定義 終於明白

1.變數的定義:變數的定義用於為變數分配儲存空間,還可以為變數指定初始值。在一個程式中,變數有且僅有一個定義。 2.變數的宣告:用於向程式表明變數的型別和名字。程式中變數可以宣告多次,但只能定義一次。 3.兩者聯絡與區別: (1)定義也是宣告,因為當定義變數時我們也向程式表