創建型模式 - 建造者模式 (Builder Pattern)
建造者模式是一種創建型設計模式,它將一個復雜對象的構建與表示分離,使得同樣的構建過程可以創建不同的表示。
需求描述
在游戲開發中,創建一個復雜的游戲角色,角色具有多種屬性,如姓名、性別、職業、武器等。不同類型的角色這些屬性的組合和設置方式可能不同。使用建造者模式可以將角色的創建過程和具體表示分離,方便創建不同類型的角色。
// 產品類:游戲角色
class GameCharacter {private String name;private String gender;private String profession;private String weapon;public void setName(String name) {this.name = name;}public void setGender(String gender) {this.gender = gender;}public void setProfession(String profession) {this.profession = profession;}public void setWeapon(String weapon) {this.weapon = weapon;}@Overridepublic String toString() {return "GameCharacter{" +"name='" + name + '\'' +", gender='" + gender + '\'' +", profession='" + profession + '\'' +", weapon='" + weapon + '\'' +'}';}
}// 抽象建造者類
abstract class CharacterBuilder {protected GameCharacter character;public GameCharacter getCharacter() {return character;}public void createNewCharacter() {character = new GameCharacter();}public abstract void buildName();public abstract void buildGender();public abstract void buildProfession();public abstract void buildWeapon();
}// 具體建造者類:戰士角色建造者
class WarriorBuilder extends CharacterBuilder {@Overridepublic void buildName() {character.setName("戰士-亞瑟");}@Overridepublic void buildGender() {character.setGender("男");}@Overridepublic void buildProfession() {character.setProfession("戰士");}@Overridepublic void buildWeapon() {character.setWeapon("大劍");}
}// 具體建造者類:法師角色建造者
class MageBuilder extends CharacterBuilder {@Overridepublic void buildName() {character.setName("法師-梅林");}@Overridepublic void buildGender() {character.setGender("男");}@Overridepublic void buildProfession() {character.setProfession("法師");}@Overridepublic void buildWeapon() {character.setWeapon("法杖");}
}// 指揮者類
class CharacterDirector {private CharacterBuilder builder;public CharacterDirector(CharacterBuilder builder) {this.builder = builder;}public GameCharacter constructCharacter() {builder.createNewCharacter();builder.buildName();builder.buildGender();builder.buildProfession();builder.buildWeapon();return builder.getCharacter();}
}// 客戶端代碼
public class GameCharacterBuilderExample {public static void main(String[] args) {// 創建戰士角色CharacterBuilder warriorBuilder = new WarriorBuilder();CharacterDirector warriorDirector = new CharacterDirector(warriorBuilder);GameCharacter warrior = warriorDirector.constructCharacter();System.out.println(warrior);// 創建法師角色CharacterBuilder mageBuilder = new MageBuilder();CharacterDirector mageDirector = new CharacterDirector(mageBuilder);GameCharacter mage = mageDirector.constructCharacter();System.out.println(mage);}
}
建造者模式拓展
使用這一種方式,就相當于代碼中調用方法者來充當指揮者角色。
public class Phone {private String cpu;private String screen;private String memory;private String brand;// 私有構造函數private Phone(Builder builder) {this.cpu = builder.cpu;this.screen = builder.screen;this.memory = builder.memory; this.brand = builder.brand;}// 內部類構造器public static final class Builder {private String cpu;private String screen;private String memory;private String brand;public Builder cpu(String cpu) {this.cpu = cpu;return this;}public Builder screen(String screen) {this.screen = screen;return this;}public Builder memory(String memory) {this.memory = memory;return this;}public Builder brand(String brand) {this.brand = brand;return this;}// 利用 Java 內部類可以訪問外部類的私有成員變量的特性,調用私有構造方法返回 Phone 對象public Phone build() {return new Phone(this);}}
}// 使用的時候非常方便也非常清晰
Phone iPhone20 = new Phone.Builder().cpu("Apple A100").screen("LG屏幕").memory("三星內存").brand("Apple").build();// btw: 這種使用方式還是挺常見的, 在一些第三方庫配置 Config 的時候,例如 Rocket MQ 配置
小結
工廠方法模式 vs 建造者模式.
工廠方法注重的是整體的構建.
建造者模式注重零部件細節的過程.
抽象工廠模式 vs 建造者模式
抽象工廠注重的是相同的產品家族同一系列產品的構建。不關心構建過程,不同的產品交給不同的具體工廠去構建.
舉例,蘋果電腦工廠,你知道結果就是一臺蘋果電腦。而如果使用建造者模式.你需要知道每個零件由什么構成.你使用不同的零件組裝出來的就是不同的電腦.