設計模式-創建型模式(二)

設計模式-創建型模式(二)

建造者模式

定義

將一個複雜對象的構造與它的表示分離,使同樣的構建過程可以創建不同的表示。它是將一個複雜的對象分解爲多個簡單對象,然後一步一步的構建而成。即產品的組成是不變的,但每一部分是可以靈活選擇的。

特點

優點

  • 各個具體的建造者相互獨立,有利於系統的擴展
  • 客戶端不必知道產品的內部組成細節,便於控制細節風險

缺點

  • 產品的組成部分必須相同,這限制了其使用範圍
  • 如果產品的內部變化複雜,該模式會增加很多的建造者類
結構

建造者模式的主要角色如下:

  • 產品(Product):它是一個複雜對象(由多個部件組成),由具體建造者來創建其各個部件。
  • 抽象建造者(Builder):定義了創建產品各個子部件的抽象方法的接口,通常還包含一個返回複雜產品的方法build()。
  • 具體建造者(Concrete Builder):實現了抽象建造者定義的接口,完成對複雜產品各個部件的具體創建方法。
  • 指揮者(Director):它調用建造者對象中的部件構造與裝配方法完成複雜對象的創建,在指揮者中不涉及具體產品的信息。
    在這裏插入圖片描述
實現

案列:汽車生產是一個複雜過程,包含發動機、車門、方向盤等,這裏通過建造者模式實現對複雜的汽車部件進行生產組裝。

/**
 *1、定義汽車產品,(包含多個部件,由具體建造者來創建各個部件)
 */
public class Car {
    //車輪
    String tyre;
    //發動機
    String engine;
    //車門
    String door;
    //方向盤(如果沒有則是自動駕駛汽車)
    String wheel;

    public void setTyre(String tyre) {this.tyre = tyre;}
    public void setEngine(String engine) {this.engine = engine;}
    public void setDoor(String door) {this.door = door;}
    public void setWheel(String wheel) {this.wheel = wheel;}
    public String getTyre() {return tyre;}
    public String getEngine() {return engine;}
    public String getDoor() {return door;}
    public String getWheel() {return wheel;}
    public void show() {
        String tyreStr = isNull(getTyre()) ? "無車輪" : "有車輪";
        String engineStr = isNull(getEngine()) ? "新能源" : "非新能源";
        String doorStr = isNull(getDoor()) ? "敞篷" : "非敞篷";
        String wheelStr = isNull(getWheel()) ? "自動駕駛" : "非自動駕駛";
        System.out.println("建造一輛" + tyreStr + engineStr + doorStr + wheelStr + "汽車");
    }
}
/**
 *2、定義抽象建造者類或接口(提供創建複雜對象部件的抽象方法,以及返回複雜產品的實例)
 */
public interface ICarBuilder {
    //創建輪胎
    void setTyre();

    //創建車門
    void setDoor();

    //創建發動機
    void setengine();

    //創建方向盤
    void setWheel();

    //返回一個複雜對象
    Car build();
}
/**
 *3、定義具體建造者,實現抽象建造者定義的抽象方法,完成對複雜對象部件的具體創建。
 */

//公共汽車建造者
public class BusBuilder implements ICarBuilder {
    
    @Override
    public void setTyre() {}

    @Override
    public void setDoor() {}

    @Override
    public void setengine() {}

    @Override
    public void setWheel() {}

    @Override
    public Car build() {
        System.out.print("公共汽車具體建造者——>");
        Car car = new Car();
        car.setTyre("有");
        car.setDoor("有");
        car.setEngine("有");
        car.setWheel("有");
        return car;
    }
}

//出租車建造者
public class TaxiBuilder implements ICarBuilder {
    
    @Override
    public void setTyre() {}

    @Override
    public void setDoor() {}

    @Override
    public void setengine() {}

    @Override
    public void setWheel() {}

    @Override
    public Car build() {
        System.out.print("出租車具體建造者——>");
        Car car = new Car();
        return car;
    }
}
/**
 *4、定義指揮者(調用具體建造者中部件構建與裝配方法完成複雜對象創建)
 *   指揮者中不涉及具體產品信息
 */
 public class Director {

    ICarBuilder iCarBuilder;

    public Director(ICarBuilder iCarBuilder) {
        this.iCarBuilder = iCarBuilder;
    }

    public Car createCar() {
        return iCarBuilder.build();
    }
} 
//測試
public class Test {
    public static void main(String[] args) {
        ICarBuilder busBuilder = new BusBuilder();
        Director director = new Director(busBuilder);
        director.createCar().show();

        ICarBuilder taxiBuilder = new TaxiBuilder();
        Director director2 = new Director(taxiBuilder);
        director2.createCar().show();
    }
}
//輸出
公共汽車具體建造者——>建造一輛有車輪非新能源非敞篷非自動駕駛汽車
出租車具體建造者——>建造一輛無車輪新能源敞篷自動駕駛汽車
應用場景

建造者(Builder)模式創建的對象是負責對象,某產品的各個部分經常面臨劇烈變化,但將它們組合在一起的算法相對穩定,所以通常在如下場景使用:

  • 創建的對象比較複雜,由多個部件構成,各部件面臨複雜變化,但構建順序是穩定的
  • 創建複雜對象短髮獨立於該對象的組成部分以及它們的裝配方式,即產品的構建過車和最終的表示是獨立的。
擴展

建造者模式在應用過程中可以根據需要改變,如果創建的產品種類只有一種,只需要一個具體建造者,這時可以省略掉抽象建造者,甚至可以省略掉指揮者角色

/**
 *創建產品(通過靜態內部類實現建造者模式)
 */
public class ExtCar {

    //車輪
    String tyre;
    //發動機
    String engine;
    //車門
    String door;
    //方向盤(如果沒有則是自動駕駛汽車)
    String wheel;

    public void setTyre(String tyre) {this.tyre = tyre;}

    public void setEngine(String engine) {this.engine = engine;}

    public void setDoor(String door) {this.door = door;}

    public void setWheel(String wheel) {this.wheel = wheel;}

    public String getTyre() {return tyre;}

    public String getEngine() {return engine;}

    public String getDoor() {return door;}

    public String getWheel() {return wheel;}

    public void show() {
        String tyreStr = isNull(getTyre()) ? "無車輪" : "有車輪";
        String engineStr = isNull(getEngine()) ? "新能源" : "非新能源";
        String doorStr = isNull(getDoor()) ? "敞篷" : "非敞篷";
        String wheelStr = isNull(getWheel() ) ? "自動駕駛" : "非自動駕駛";
        System.out.println("建造一輛" + tyreStr + engineStr + doorStr + wheelStr + "汽車");
    }

    //靜態內部類實現建造者模式
    public static class Builder {
        //車輪
        String tyre;
        //發動機
        String engine;
        //車門
        String door;
        //方向盤(如果沒有則是自動駕駛汽車)
        String wheel;

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

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

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

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

        public ExtCar build() {
            ExtCar extCar = new ExtCar();
            extCar.setTyre(tyre);
            extCar.setEngine(engine);
            extCar.setDoor(door);
            extCar.setWheel(wheel);
            return extCar;
        }
    }
}
//測試
public class Test {
    public static void main(String[] args) {
        //選擇性構建部件
        ExtCar car1 = new ExtCar.Builder()
                .setTyre("有")
                .setEngine("有")
                .build();
        car1.show();
       //選擇性構建部件,與car1構建過程一致,但最終表示不同
        ExtCar car2 = new ExtCar.Builder()
                .setDoor("有")
                .setWheel("有")
                .build();
        car2.show();
    }
}
//輸出
建造一輛有車輪非新能源敞篷自動駕駛汽車
建造一輛無車輪新能源非敞篷非自動駕駛汽車

原型模式

定義

用一個已經創建的實例作爲原型,通過複製該原型來創建一個和原型相同或相似的對象。在這裏,原型實例指定了要創建的對象種類,用這種方式創建對象非常高效,根本無需知道對象的創建細節。

結構

原型模式包含一下角色

  • 抽象原型類:規定了具體原型對象必須要實現的接口。
  • 具體原型類:實現了抽象原型類的clone()方法,它是可以被複制的對象。
  • 訪問類:使用具體原型類中的clone()方法來複制新的對象的類。
    在這裏插入圖片描述
實現

原型模式的克隆分爲淺克隆深克隆,Java 中的 Object 類提供了淺克隆的 clone() 方法,具體原型類只要實現 Cloneable 接口就可實現對象的淺克隆,這裏的 Cloneable 接口就是抽象原型類。

用原型模式除了可以生成相同的對象,還可以生成相似(部分屬性不同)對象。

案例:同一三好學生獎狀除了人名不同,其他都相同,屬於相似對象,可以通過原型模式實現,然後再做簡單修改即可

/**
 *1、具體原型類(實現抽象原型類Cloneable接口的clone()方法)-獎狀
 */
public class Citation implements Cloneable {

    String name;
    String info;

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}

    public String getInfo() {return info;}

    public void setInfo(String info) {this.info = info;}

    public Citation(String name, String info) {
        this.name = name;
        this.info = info;
    }

    public void show() {System.out.println(getName() + getInfo());}

    //重寫抽象原型類中的cone()方法
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
//訪問類
public class Test {
    public static void main(String[] args) {
         Citation zhangsan = new Citation("張三", "同學,在2019年第一學年度被評爲三好學生,"+
                                          "特發此狀以此鼓勵!");
         zhangsan.show();
        try {
            //使用原型模式復創建新對象
            Citation lisi = (Citation) zhangsan.clone();
            //修改部分屬性
            lisi.setName("李四");
            lisi.show();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

//輸出
張三同學,在2019年第一學年度被評爲三好學生,特發此狀以此鼓勵!
李四同學,在2019年第一學年度被評爲三好學生,特發此狀以此鼓勵!
應用場景

原型模式適用於以下場景

  • 對象之間相同或相似,即只是個別的幾個屬性不同的時候。
  • 對象的創建過程比較麻煩,但是複製比較簡單的時候。

參考文獻

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章