天天看點

java建構者模式Builder

定義

Builder模式是一步步建立一個複雜對象的建立型模式,它允許使用者在不知道内部建構細節的情況下,可以更精細的控制對象的建構過程。該模式是将建構複雜對象的過程和它的部件解耦,使得建構過程和部件的表示隔離。

作為複雜對象可能有很多組成部分,比如汽車有車輪、方向盤、發動機、變速箱還有各種小零件等,如何将這些部件組裝成一台汽車,這個裝配的過程漫長且複雜,對于這種情況,為了對外部隐藏實作細節,就可以使用Builder模式将部件群組裝過程分離,使得建構過程和部件分離可自由擴充,兩者之間的耦合也降到最低

使用場景

1、相同的方法,不同的執行順序、産生不同的事件結果時

2、多個部件或零件都可以組裝到一個對象中,但産生的結果不相同時

3、産品類非常複雜,或者産品類中的調用順序不同産生不同的作用,這個時候使用Builder模式非常合适

4、當初始化一個對象特别複雜,比如參數多,且很多參數都具有預設值時。

Product産品類---------産品的抽象類

Builder------------------抽象Builder類,規範産品的組建,一般是由子類實作具體的建構過程

ConcreteBuilder-------具體Builder類

Director------------------統一組裝過程

package com.example.myjavademo;

/**
 * 計算機的組裝過程較為複雜,并且組裝過程不固定,為了易于了解,我們把計算機組裝過程簡化為
 * 建構主機、設定作業系統、設定顯示器3步,然後通過Directer和具體Builder來建構計算機對象
 *
 */
public class BuilderDesignDemo {
    public static void main(String []args){
        //方式一
        Builder builder=new MACBookBuilder();
        Director director=new Director(builder);
        director.construct("intel","AOC");
        System.out.println(builder.create().toString());


        //方式2
        System.out.println(new MACBookBuilder().
                buildBoard("intel").buildDisplay("AOC").create().toString());


    }
}

/**
 * 計算機抽象類,即Product角色
 */
abstract class Computer{

    protected String mBoard;
    protected String mDisplay;
    protected String mOS;
    protected Computer(){

    }
    public void setBoard(String board){//具體什麼實作進行了隐藏

        this.mBoard=board;
    }
    public void setDisplay(String display){//具體什麼實作進行了隐藏
        this.mDisplay=display;
    }
    public abstract void setOS();

    @Override
    public String toString() {
        return "Computer:="+mBoard+",="+mOS+",="+mDisplay;
    }
}

/**
 * 具體的Computer類
 */

class MACBook extends Computer{
    protected MACBook(){};
    @Override
    public void setOS() {
        mOS="MAC OS X";
    }
}

/**
 * 抽象Builder類
 */
abstract class Builder{
    //設定主機
    public abstract Builder buildBoard(String board);
    //設定作業系統
    public abstract Builder buildOS();
    //設定顯示器
    public abstract Builder buildDisplay(String display);
    //建立Computer
    public abstract Computer create();
}

/**
 * 具體Builder類,MACBookBuilder
 */
class MACBookBuilder extends Builder{
    private Computer computer=new MACBook();

    @Override
    public Builder buildBoard(String board) {
        computer.setBoard(board);
        return this;
    }

    @Override
    public Builder buildOS() {
        computer.setOS();
        return this;
    }

    @Override
    public Builder buildDisplay(String display) {
        computer.setDisplay(display);
        return this;
    }

    @Override
    public Computer create() {//Mac的作業系統肯定是MAC OS的;這部分對外部隐藏
        computer.setOS();
        return computer;
    }
}

/**
 * Director類,負責建構Computer
 */
class Director{
    Builder builder=null;

    public Director(Builder builder) {
        this.builder = builder;
    }
    /**
     * 建構對象
     */
    public void construct(String board,String display){
        builder.buildBoard(board);
        builder.buildDisplay(display);

    }
}

           

上述示例中,通過具體的MacBoookBuilde來建構具體的MacBook對象,而Director封裝了建構複雜産品對象的過程,對外隐藏建構細節。Builder和Director一起将一個複雜對象的建構與他的表示分離,使得同樣的建構過程可以建立不同的對象。

值得注意的是,在現實開發過程中,Director角色經常被省略。而直接使用Builder來進行對象的組裝,這個Builder通常為鍊式調用,他的關鍵點是每個setter都傳回自身,也就是 return this,這樣的setter方法可以鍊式調用,如以上方式二,通過這種方式不僅去除了Director角色,這個結構也更加簡單,也能對Proctor對象的組裝過程有更精細的控制

第二個例子

public class BuilderDemo {

    public static void main(String []args){
        System.out.println( new CarBuilder.Builder().buildEngine("V8發動機").build());;
    }


}


class CarBuilder{
    public static final class Builder {
        String engine;
        String gearbox;
        String underpan;

        public Builder() {
            engine = "預設引擎";
            gearbox = "預設變速箱";
            underpan = "預設底盤";
        }

        public Builder buildEngine(String strEngin) {
            this.engine=strEngin;
            return this;
        }

        public Builder buildGearbox(String strGearbox) {
            this.gearbox=strGearbox;
            return this;
        }

        public Builder buildUnderpan(String strUnderpan) {
            this.underpan=strUnderpan;
            return this;
        }

        public String build(){
            return engine+gearbox+underpan;
        }

    }
}