將一個複雜對象的建立與它的表示分離,使得一樣的建立過程能夠建立不一樣的表示java
假設構造函數中有十個可選參數,那麼調用該函數會很是不方便;所以,須要重載這個構造函數,新建幾個只有較少參數的簡化版。可是這些構造函數仍需調用主構造函數,傳遞一些默認數值來代替省略掉的參數算法
class Pizza { Pizza(int size) { ... } Pizza(int size, boolean cheese) { ... } Pizza(int size, boolean cheese, boolean pepperoni) { ... } // ...
1) 能夠改變一個產品的內部表示 Builder對象提供給導向器一個構造產品的抽象接口,產品是經過抽象接口構造的。該接口使得生成器能夠隱藏這個產品的表示和內部結構。當時須要改變產品的內部結構,只須要定義一個新的生成器app
2) 將構造代碼和表示代碼分開 Builder模式經過封裝一個複雜對象的建立和表示方式提升了對象的模塊性。每一個Concretebuilder包含了建立和裝配一個特定產品的全部代碼。Director能夠複用它以在相同部件集合的基礎上構建不一樣的productide
3)對構造過程進行更精細的控制 Builder模式是在導向器的控制下,一步一步構造產品的。僅當產品完成時,導向器才從生成器中取回它。所以,builder接口相比其餘建立型模式能更好的反映產品的構造過程,這使咱們能夠更精細的控制構造過程函數
builders/Builder.java: 通用生成器接口ui
package builder.builders; import builder.cars.CarType; import builder.components.Engine; import builder.components.GPSNavigator; import builder.components.Transmission; import builder.components.TripComputer; /** * @author GaoMing * @date 2021/7/18 - 9:58 * Builder interface defines all possible ways to configure a product */ public interface Builder { void setCarType(CarType type); void setSeats(int seats); void setEngine(Engine engine); void setTransmission(Transmission transmission); void setTripComputer(TripComputer tripComputer); void setGPSNavigator(GPSNavigator gpsNavigator); }
builders/CarBuilder.java: 汽車生成器this
package builder.builders; import builder.cars.Car; import builder.cars.CarType; import builder.components.Engine; import builder.components.GPSNavigator; import builder.components.Transmission; import builder.components.TripComputer; /** * @author GaoMing * @date 2021/7/18 - 10:01 */ public class CarBuilder implements Builder{ private CarType type; private int seats; private Engine engine; private Transmission transmission; private TripComputer tripComputer; private GPSNavigator gpsNavigator; public void setCarType(CarType type) { this.type = type; } @Override public void setSeats(int seats) { this.seats = seats; } @Override public void setEngine(Engine engine) { this.engine = engine; } @Override public void setTransmission(Transmission transmission) { this.transmission = transmission; } @Override public void setTripComputer(TripComputer tripComputer) { this.tripComputer = tripComputer; } @Override public void setGPSNavigator(GPSNavigator gpsNavigator) { this.gpsNavigator = gpsNavigator; } public Car getResult() { return new Car(type, seats, engine, transmission, tripComputer, gpsNavigator); } }
builders/CarManualBuilder.java: 汽車手冊生成器spa
package builder.builders; import builder.cars.CarType; import builder.cars.Manual; import builder.components.Engine; import builder.components.GPSNavigator; import builder.components.Transmission; import builder.components.TripComputer; /** * @author GaoMing * @date 2021/7/18 - 10:03 * Unlike other creational patterns, Builder can construct unrelated products, * which don't have the common interface. * In this case we build a user manual for a car, using the same steps as we * built a car. This allows to produce manuals for specific car models, * configured with different features. */ public class CarManualBuilder implements Builder{ private CarType type; private int seats; private Engine engine; private Transmission transmission; private TripComputer tripComputer; private GPSNavigator gpsNavigator; @Override public void setCarType(CarType type) { this.type = type; } @Override public void setSeats(int seats) { this.seats = seats; } @Override public void setEngine(Engine engine) { this.engine = engine; } @Override public void setTransmission(Transmission transmission) { this.transmission = transmission; } @Override public void setTripComputer(TripComputer tripComputer) { this.tripComputer = tripComputer; } @Override public void setGPSNavigator(GPSNavigator gpsNavigator) { this.gpsNavigator = gpsNavigator; } public Manual getResult() { return new Manual(type, seats, engine, transmission, tripComputer, gpsNavigator); } }
cars/Car.java: 汽車產品3d
package builder.cars; import builder.components.Engine; import builder.components.GPSNavigator; import builder.components.Transmission; import builder.components.TripComputer; /** * @author GaoMing * @date 2021/7/18 - 9:48 * Car is a product class */ public class Car { private final CarType carType; private final int seats; private final Engine engine; private final Transmission transmission; private final TripComputer tripComputer; private final GPSNavigator gpsNavigator; private double fuel = 0; public Car(CarType carType, int seats, Engine engine, Transmission transmission, TripComputer tripComputer, GPSNavigator gpsNavigator) { this.carType = carType; this.seats = seats; this.engine = engine; this.transmission = transmission; this.tripComputer = tripComputer; if (this.tripComputer != null) { this.tripComputer.setCar(this); } this.gpsNavigator = gpsNavigator; } public CarType getCarType() { return carType; } public double getFuel() { return fuel; } public void setFuel(double fuel) { this.fuel = fuel; } public int getSeats() { return seats; } public Engine getEngine() { return engine; } public Transmission getTransmission() { return transmission; } public TripComputer getTripComputer() { return tripComputer; } public GPSNavigator getGpsNavigator() { return gpsNavigator; } }
cars/Manual.java: 手冊產品code
package builder.cars; import builder.components.Engine; import builder.components.GPSNavigator; import builder.components.Transmission; import builder.components.TripComputer; /** * @author GaoMing * @date 2021/7/18 - 9:56 * Car manual is another product. Note that it does not have the same ancestor as a Car. They are not related */ public class Manual { private final CarType carType; private final int seats; private final Engine engine; private final Transmission transmission; private final TripComputer tripComputer; private final GPSNavigator gpsNavigator; public Manual(CarType carType, int seats, Engine engine, Transmission transmission, TripComputer tripComputer, GPSNavigator gpsNavigator) { this.carType = carType; this.seats = seats; this.engine = engine; this.transmission = transmission; this.tripComputer = tripComputer; this.gpsNavigator = gpsNavigator; } public String print() { String info = ""; info += "Type of car: " + carType + "\n"; info += "Count of seats: " + seats + "\n"; info += "Engine: volume - " + engine.getVolume() + "; mileage - " + engine.getMileage() + "\n"; info += "Transmission: " + transmission + "\n"; if (this.tripComputer != null) { info += "Trip Computer: Functional" + "\n"; } else { info += "Trip Computer: N/A" + "\n"; } if (this.gpsNavigator != null) { info += "GPS Navigator: Functional" + "\n"; } else { info += "GPS Navigator: N/A" + "\n"; } return info; } }
cars/CarType.java
package builder.cars; /** * @author GaoMing * @date 2021/7/18 - 9:51 */ public enum CarType { CITY_CAR, SPORTS_CAR, SUV }
components/Engine.java: 產品特徵 1
package builder.components; /** * @author GaoMing * @date 2021/7/18 - 9:27 * feature of a car */ public class Engine { private final double volume; private double mileage; private boolean started; public Engine(double volume, double mileage){ this.volume = volume; this.mileage = mileage; } public void on(){ started = true; } public void off(){ started = false; } public boolean isStarted(){ return started; } public void go(double mileage){ if(started){ this.mileage += mileage; }else { System.err.println("Cannot go(), you must start engine first!"); } } public double getVolume(){ return volume; } public double getMileage(){ return mileage; } }
components/GPSNavigator.java: 產品特徵 2
package builder.components; /** * @author GaoMing * @date 2021/7/18 - 9:33 * Another feature of a car */ public class GPSNavigator { private String route; public GPSNavigator(){ this.route = "221b, Baker Street, London to Scotland Yard, 8-10 Broadway, London"; } public GPSNavigator(String manualRoute){ this.route = manualRoute; } public String getRoute(){ return route; } }
components/Transmission.java: 產品特徵 3
package builder.components; /** * @author GaoMing * @date 2021/7/18 - 9:35 * Another feature of a car */ public enum Transmission { SINGLE_SPEED, MANUAL, AUTOMATIC, SEMI_AUTOMATIC }
components/TripComputer.java: 產品特徵 4
package builder.components; import builder.cars.Car; /** * @author GaoMing * @date 2021/7/18 - 9:48 * Another feature of a car */ public class TripComputer { private Car car; public void setCar(Car car){ this.car = car; } public void showFuellevel(){ System.out.println("Fuel level: " + car.getFuel()); } public void showStatus(){ if(this.car.getEngine().isStarted()){ System.out.println("Car is started"); }else { System.out.println("Car isn't started"); } } }
director/Director.java: 主管控制生成器
package builder.director; import builder.cars.CarType; import builder.components.Engine; import builder.components.GPSNavigator; import builder.components.Transmission; import builder.components.TripComputer; import builder.builders.Builder; /** * @author GaoMing * @date 2021/7/18 - 10:08 * Director defines the order of building steps. It works with a builder object * through common Builder interface. Therefore it may not know what product is * being built. */ public class Director { public void constructSportsCar(Builder builder) { builder.setCarType(CarType.SPORTS_CAR); builder.setSeats(2); builder.setEngine(new Engine(3.0, 0)); builder.setTransmission(Transmission.SEMI_AUTOMATIC); builder.setTripComputer(new TripComputer()); builder.setGPSNavigator(new GPSNavigator()); } public void constructCityCar(Builder builder) { builder.setCarType(CarType.CITY_CAR); builder.setSeats(2); builder.setEngine(new Engine(1.2, 0)); builder.setTransmission(Transmission.AUTOMATIC); builder.setTripComputer(new TripComputer()); builder.setGPSNavigator(new GPSNavigator()); } public void constructSUV(Builder builder) { builder.setCarType(CarType.SUV); builder.setSeats(4); builder.setEngine(new Engine(2.5, 0)); builder.setTransmission(Transmission.MANUAL); builder.setGPSNavigator(new GPSNavigator()); } }
Demo.java: 客戶端代碼
package builder; import builder.builders.CarBuilder; import builder.builders.CarManualBuilder; import builder.cars.Car; import builder.cars.Manual; import builder.director.Director; /** * @author GaoMing * @date 2021/7/18 - 10:13 * Demo class. Everything comes together here. */ public class demo { public static void main(String[] args) { Director director = new Director(); // Director gets the concrete builder object from the client // (application code). That's because application knows better which // builder to use to get a specific product. CarBuilder builder = new CarBuilder(); director.constructSportsCar(builder); // The final product is often retrieved from a builder object, since // Director is not aware and not dependent on concrete builders and // products. Car car = builder.getResult(); System.out.println("Car built:\n" + car.getCarType()); CarManualBuilder manualBuilder = new CarManualBuilder(); // Director may know several building recipes. director.constructSportsCar(manualBuilder); Manual carManual = manualBuilder.getResult(); System.out.println("\nCar manual built:\n" + carManual.print()); } }
OutputDemo.txt: 執行結果
Car built: SPORTS_CAR Car manual built: Type of car: SPORTS_CAR Count of seats: 2 Engine: volume - 3.0; mileage - 0.0 Transmission: SEMI_AUTOMATIC Trip Computer: Functional GPS Navigator: Functional
生成器重點關注如何分步生成複雜對象。 抽象工廠專門用於生產一系列相關對象。 抽象工廠會立刻返回產品, 生成器則容許你在獲取產品前執行一些額外構造步驟。
Composite一般是由Builder生成的
識別方法: 生成器模式能夠經過類來識別, 它擁有一個構建方法和多個配置結果對象的方法。 生成器方法一般支持方法鏈 (例如 someBuilder->setValueA(1)->setValueB(2)->create() )