抽象工廠是對工廠的抽象化,而不只是制造方法。
為了滿足不同用戶對產品的多樣化需求,工廠不會只局限于生產一類產品,但是系統如果按工廠方法那樣為每種產品都增加一個工廠又會造成工廠泛濫。所以,為了調和這種矛盾,抽象工廠模式提供了另一種思路,將各種產品分門別類,基于此來規劃各種工廠的制造接口,最終確立產品制造的頂級規范。
一、品牌與系列
在工廠方法模式種每個實際的工廠直定義了一個工廠方法。而隨著經濟發展,人們對產品的需求不斷升級,并逐漸走向個性化、多元化,制造業隨之壯大起來。各類工廠遍地開發,能夠制造的產品種類也豐富了起來,隨之而來的弊端就是工廠泛濫。
針對這種情況,進行產業規劃與整合,對現有工廠進行重構。
- 可以基于產品品牌與系列進行生產線規劃,按品牌分成A工廠與B工廠
- 基于這兩個品牌汽車工廠的系列生產線,如果今后產生新的C品牌汽車、D品牌汽車等,都可以沿用此種規劃好的生產模式,這便是抽象工廠模式的基礎數據模型。
二、產品規劃
無論哪種工廠模式,都一定是基于特定的產品特性發展而來的。假如公司要開發一款星際戰爭游戲,戰爭設定在太陽系文明與外星文明之間展開,游戲兵種就可以分為人類和外星怪獸兩個族。
?人類有各種軍工高科技裝備、外星靠血肉之軀與人類戰斗。所以將兵種按照族進行劃分。
兵種規劃表格以列劃分等級,以行劃分族,一目了然,我們可以根據這個建立數據模型。
首先,我們來定義一個所有兵種的頂級父類兵種,這里我們使用抽象類,以達到屬性繼承給子類的目的。
public abstract class Unit {protected int attack; // 攻擊力protected int defence; // 防御力protected int health; // 生命力protected int x; // 橫坐標protected int y; // 縱坐標public Unit(int attack, int defence, int health, int x, int y) {this.attack = attack;this.defence = defence;this.health = health;this.x = x;this.y = y;}public abstract void show();public abstract void attack();
}
任何兵種都有攻擊力、防御力、生命力、坐標方位等屬性。
接下來我們將兵種按等級分類,假設同一等級的攻擊力、防御力等屬性值是相同的,所以初級、中級、高級兵種會分別對應三個等級的兵種類:
1.?初級兵種類 LowClassUnit
public abstract class LowClassUnit extends Unit {public LowClassUnit(int x, int y) {super(5, 2, 35, x, y);}
}
2.?中級兵種類 MidClassUnit
public abstract class MidClassUnit extends Unit {public MidClassUnit(int x, int y) {super(10, 8, 80, x, y);}
}
3.?高級兵種類 HighClassUnit
public abstract class HighClassUnit extends Unit {public HighClassUnit(int x, int y) {super(25, 30, 300, x, y);}
}
各等級兵種類都繼承自兵種抽象類Unit,接下來定義具體的兵種類:
1.?海軍陸戰隊員類 Marine
public class Marine extends LowClassUnit {public Marine(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("士兵出現在坐標: [" + x + "," + y + "]");}@Overridepublic void attack() {System.out.println("士兵用機關槍射擊,攻擊力: " + attack);}
}
2.?變形坦克類 Tank
public class Tank extends MidClassUnit {public Tank(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("坦克出現在坐標: [" + x + "," + y + "]");}@Overridepublic void attack() {System.out.println("坦克用炮轟擊,攻擊力: " + attack);}
}
3.?巨型戰艦類 Battleship
public class Battleship extends HighClassUnit {public Battleship(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("戰艦出現在坐標: [" + x + "," + y + "]");}@Overridepublic void attack() {System.out.println("戰艦用激光炮打擊,攻擊力: " + attack);}
}
如圖,我們構造方法中調用了父類,并初始化了坐標屬性,其攻擊力、防御力和生命力已經在對應等級的父類里面初始化好了。
1.?蟑螂類 Roach
public class Roach extends LowClassUnit {public Roach(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("蟑螂兵出現在坐標: [" + x + "," + y + "]");}@Overridepublic void attack() {System.out.println("蟑螂兵用爪子撓,攻擊力: " + attack);}
}
2.?毒液類 Poison
public class Poison extends MidClassUnit {public Poison(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("毒液兵出現在坐標: [" + x + "," + y + "]");}@Overridepublic void attack() {System.out.println("毒液兵用毒液噴射,攻擊力: " + attack);}
}
3.?猛犸類 Mammoth
public class Mammoth extends HighClassUnit {public Mammoth(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("猛犸巨獸出現在坐標: [" + x + "," + y + "]");}@Overridepublic void attack() {System.out.println("猛犸巨獸用獠牙頂,攻擊力: " + attack);}
}
至此,所有兵種類已經定義完畢,代碼不是難點,重點集中在對兵種的劃分上,橫向劃分族、縱向劃分等級,利用類的抽象與繼承描繪出所有的游戲角色以及他們之間的關系,同時避免了不少重復代碼。
三、生產線規劃
既然產品類的數據模型構建完成,相應的產品線也應該建立起來,接下來就定義這些產品的制造工廠。我們一共定義了6個兵種產品,那么每個產品都要對應一個工廠類嗎?答案是否定的。
人類兵工廠是高度工具化的、怪獸靠母巢繁殖,所以應該將工廠分為兩個族,并且每個族工廠有3個等級兵種的制造方法。
如此規劃不但合理,而且避免了工廠類泛濫的問題。
1. 抽象兵工廠接口定義了三個等級兵種的制造標準
意味著子類工廠必須具備初級、中級、高級兵種的生產能力。
public interface AbstractFactory {LowClassUnit createLowClass(); // 初級兵種制造標準MidClassUnit createMidClass(); // 中級兵種制造標準HighClassUnit createHighClass(); // 高級兵種制造標準
}
2.?HumanFactory 類
public class HumanFactory implements AbstractFactory {private int x; // 工廠橫坐標private int y; // 工廠縱坐標public HumanFactory(int x, int y) {this.x = x;this.y = y;}@Overridepublic LowClassUnit createLowClass() {LowClassUnit unit = new Marine(x, y);System.out.println("制造海軍陸戰隊員成功.");return unit;}@Overridepublic MidClassUnit createMidClass() {MidClassUnit unit = new Tank(x, y);System.out.println("制造變形坦克成功.");return unit;}@Overridepublic HighClassUnit createHighClass() {HighClassUnit unit = new Battleship(x, y);System.out.println("制造巨型戰艦成功.");return unit;}
}
2.?AlienFactory 類
public class AlienFactory implements AbstractFactory {private int x; // 工廠橫坐標private int y; // 工廠縱坐標public AlienFactory(int x, int y) {this.x = x;this.y = y;}@Overridepublic LowClassUnit createLowClass() {LowClassUnit unit = new Roach(x, y);System.out.println("制造蟑螂兵成功.");return unit;}@Overridepublic MidClassUnit createMidClass() {MidClassUnit unit = new Poison(x, y);System.out.println("制造毒液兵成功.");return unit;}@Overridepublic HighClassUnit createHighClass() {HighClassUnit unit = new Mammoth(x, y);System.out.println("制造猛犸巨獸成功.");return unit;}
}
人類兵工廠與外星母巢分別實現了三個等級兵種的制造方法,其中前者由低到高分別返回海軍陸戰隊員、變形坦克以及巨型戰艦對象,后者則分別返回蟑螂兵、毒液兵以及猛犸獸對象,生產線規劃非常清晰。
客戶端調用
public class Client {public static void main(String[] args) {System.out.println("游戲開始……");System.out.println("雙方挖礦攢錢……");// 第一位玩家選擇了人類族System.out.println("工人建造人類族工廠……");AbstractFactory factory = new HumanFactory(10, 10);Unit marine = factory.createLowClass();marine.show();Unit tank = factory.createMidClass();tank.show();Unit ship = factory.createHighClass();ship.show();// 第二位玩家選擇了外星怪獸族System.out.println("工蜂建造外星怪獸族工廠……");factory = new AlienFactory(200, 200);Unit roach = factory.createLowClass();roach.show();Unit poison = factory.createMidClass();poison.show();Unit mammoth = factory.createHighClass();mammoth.show();System.out.println("兩族開始大混戰……");marine.attack();roach.attack();poison.attack();tank.attack();mammoth.attack();ship.attack();}
}
至此,抽象工廠制造模式已經布局完成。
產品雖然繁多,但總有品牌、系列之分。基于此抽象工廠模式以品牌與系列進行全局規劃,將看似雜亂無章的產品規劃到不同的族系,再通過抽象工廠管理起來,分而治之,合縱連橫。
需要注意的是,抽象工廠模式一定是基于產品的族系來劃分布局的,其產品邪獵一定是相對固定的,固以抽象工廠來確立工業制造標準。而產品族則可以相對靈活多變,如此一來,我們就可以方便的擴展與替換族工廠,以達到靈活產出各類產品族系的目的。
-- 秒懂設計模式學習筆記
-- 抽象工廠