建造者模式
概念
建造者模式是設計模式的一種,將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
角色
- 抽象建造者: 爲創建一個產品對象的各個部分指定抽象接口。通常有兩類方法,一類是buildPartX(),用於創建複雜對象的各個部分;另一類是getResult(),用於返回複雜對象
- 具體建造者: 實現了抽象建造者的接口,實現了各個部分的具體構造和裝配方法,定義並明確所創建的複雜對象
- 產品: 被構造的複雜對象,包括多個組件
- 指揮者: 安排複雜對象的建造次序,客戶端一般只需要和指揮者進行交互
UML圖如下
建造者模式的優缺點
優點
- 客戶端不需要知道產品內部組成,將產品本身與產品的創建過程進行解耦
- 每一個具體建造者都相對獨立。方便替換具體建造者或增加新的具體建造者,符合開閉原則
- 將複雜產品的創建步驟分解在不同點的方法中,使得創建過程更加清晰
缺點
- 如果產品間差異很大,不適合用建造者模式
- 如果產品的內容變化複雜,可能會導致需要定義很多具體建造者類來實現這種變化,導致系統變得很龐大
適合環境
- 產品對象有複雜的內部結構
- 產品對象的屬性相互依賴,需要指定其生產順序
- 創建過程獨立於創建該對象的類
- 隔離複雜對象的創建和使用
例子
我們現在要開發一款角色扮演遊戲,玩具可以創建不同的角色,不同的角色具有不同的能力。角色作爲遊戲的一個重要組成部分,需要對角色進行設計,而且伴隨着遊戲的更新會不斷添加新角色,遊戲角色是一個複雜對象,包含性別、髮型、服裝等都有所差異。如天使擁有美麗的面容和披肩長髮,身穿白裙;惡魔及其醜陋並且光頭穿一身黑衣服。我們需要創建出該遊戲的角色
分析
我們先將實體與簡單工廠的角色一一對應
- 複雜產品對象: Action
- 抽象建造者: ActionBuilder
- 具體建造者: HeroBuilder
- 具體建造者: AngelBuilder
- 具體建造者: DevilBuilder
- 指揮者: ActionController
看不懂不要緊,我們先看UML圖,在看代碼應該就能理解了
[外鏈圖片轉存失敗(img-5OPwRgiC-1564501958249)(https://raw.githubusercontent.com/kevinlu98/cloudimg/master/data/[email protected])]
編碼
當然,具體的遊戲開發比我們這個僞代碼難多了,我們就是模擬一下這個過程
Action.java
package cn.kevinlu98.builder;
/**
* @Author: Kevin·Lu
* @Date: 12:20 AM 2019/7/28
* @Description: 遊戲角色類,充當複雜產品對象。
*/
public class Actor {
private String type; //角色類型
private String sex; //性別
private String face; //臉型
private String costume; //服裝
private String hairstyle; //髮型
//getter and setter
}
ActionBuilder.java
package cn.kevinlu98.builder;
/**
* @Author: Kevin·Lu
* @Date: 12:24 AM 2019/7/28
* @Description: 遊戲角色建造者,充當抽象建造者
*/
public abstract class ActorBuilder {
protected Actor actor = new Actor();
public abstract void buildType();
public abstract void buildSex();
public abstract void buildFace();
public abstract void buildCustomer();
public abstract void buildHairstyle();
/**
* 工廠方法,返回一個完整的角色對象
*
* @return
*/
public Actor createActor() {
return actor;
}
}
HeroBuilder.java
package cn.kevinlu98.builder;
/**
* @Author: Kevin·Lu
* @Date: 12:27 AM 2019/7/28
* @Description: 英雄角色建造者,充當具體建造者
*/
public class HeroBuilder extends ActorBuilder {
@Override
public void buildType() {
actor.setType("英雄");
}
@Override
public void buildSex() {
actor.setSex("男");
}
@Override
public void buildFace() {
actor.setFace("英俊");
}
@Override
public void buildCustomer() {
actor.setCostume("盔甲");
}
@Override
public void buildHairstyle() {
actor.setHairstyle("飄逸");
}
}
AngelBuilder.java
package cn.kevinlu98.builder;
/**
* @Author: Kevin·Lu
* @Date: 12:29 AM 2019/7/28
* @Description: 天使角色建造者,充當具體建造者
*/
public class AngelBuilder extends ActorBuilder {
@Override
public void buildType() {
actor.setType("天使");
}
@Override
public void buildSex() {
actor.setSex("女");
}
@Override
public void buildFace() {
actor.setFace("漂亮");
}
@Override
public void buildCustomer() {
actor.setCostume("白裙");
}
@Override
public void buildHairstyle() {
actor.setHairstyle("披肩長髮");
}
}
DevilBuilder.java
package cn.kevinlu98.builder;
/**
* @Author: Kevin·Lu
* @Date: 12:30 AM 2019/7/28
* @Description: 惡魔角色建造者,充當具體建造者
*/
public class DevilBuilder extends ActorBuilder {
@Override
public void buildType() {
actor.setType("惡魔");
}
@Override
public void buildSex() {
actor.setSex("妖");
}
@Override
public void buildFace() {
actor.setFace("醜陋");
}
@Override
public void buildCustomer() {
actor.setCostume("黑衣");
}
@Override
public void buildHairstyle() {
actor.setHairstyle("光頭");
}
}
ActionController.java
package cn.kevinlu98.builder;
/**
* @Author: Kevin·Lu
* @Date: 12:31 AM 2019/7/28
* @Description: 角色控制器,充當指揮者
*/
public class ActorController {
public Actor construct(ActorBuilder builder) {
builder.buildCustomer();
builder.buildFace();
builder.buildHairstyle();
builder.buildSex();
builder.buildType();
return builder.createActor();
}
}
config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<className>cn.kevinlu98.builder.AngelBuilder</className>
</config>
XMLUtil.java(略,和之前的大同小異)
運行結果
至此,工廠方法設計模式介紹完成,希望能幫助到您