抽象工廠模式
抽象工廠模式(Abstract Factory Pattern)是所有形態(tài)的工廠模式中最為抽象和最具一般性的一種形態(tài)。抽象工廠模式是指當有多個抽象角色時,使用的一種工廠模式。抽象工廠模式可以向客戶端提供一個接口,使客戶端在不必指定產(chǎn)品的具體的情況下,創(chuàng)建多個產(chǎn)品族中的產(chǎn)品對象。
- 如果讀者不了解工廠模式,請看上篇【設計模式】工廠模式。
UML類圖
- 抽象產(chǎn)品類(AbstractProductX):多個系列抽象產(chǎn)品(X=A,B,C...)。
- 具體產(chǎn)品類(ProductX):實現(xiàn)基類中的抽象方法(多個不同的具體產(chǎn)品,X=1,2,3..)。
- 抽象工廠類或接口(AbstractFactory):定義具體工廠的多個公共接口(擁有各系列產(chǎn)品創(chuàng)建的接口)。
- 具體工廠類(FactoryX):定義創(chuàng)建各系列具體產(chǎn)品實例的方法。(每個工廠對應一種具體產(chǎn)品,X=1,2,3...)。
與工廠模式的區(qū)別
- 工廠模式的工廠只能生產(chǎn)一個系列的產(chǎn)品。而抽象工廠模式的工廠可以生產(chǎn)一個或多個系列的產(chǎn)品。
- 工廠模式關注的是一個系列的不同種產(chǎn)品。而抽象工廠模式關注的是不同系列產(chǎn)品。
案例分析
接著上篇【設計模式】工廠模式的話題。
場景:玩《英雄聯(lián)盟》(5v5 moba端游)新開一局游戲,游戲開始每個玩家需要選一個英雄之外,還需要選擇天賦,召喚師技能。也就是需要創(chuàng)建三種產(chǎn)品。并且,在不同玩法下,比如召喚師峽谷(自選或排位等)與哭嚎深淵(大亂斗),創(chuàng)建的產(chǎn)品也略微有所差異,比如大亂斗下英雄一開始就3級,召喚師技能沒有傳送,有雪球。結構上:
- 產(chǎn)品(三個系列):英雄,天賦,召喚師技能。
- 工廠(兩個):召喚師峽谷工廠,哭嚎深淵工廠。
代碼實現(xiàn)
英雄基類(新增lv
成員變量和print()
方法)
public abstract class Hero {
protected String name;
protected int lv;
public abstract void say();
public void print() {
System.out.println("name:" + name);
System.out.println("lv:" + lv);
}
}
只考慮一種英雄,比如寒冰射手-艾希。
艾希類:
public class Ashe extends Hero {
// 簡化構造方法,只弄個名字。
public Ashe() {
this.name = "寒冰射手-艾希";
}
// 艾希臺詞(不重要)
@Override
public void say() {
System.out.println(name + ":" + "世間萬物皆系于一箭之上。");
}
}
召喚師峽谷中的艾希:
public class Ashe_XiaGu extends Ashe {
// 在召喚師峽谷中初始等級1級。
public Ashe_XiaGu() {
super();
this.lv = 1;
}
}
哭嚎深淵中的艾希:
public class Ashe_ShenYuan extends Ashe {
// 在哭嚎深淵中初始等級3級。
public Ashe_ShenYuan() {
super();
this.lv = 3;
}
}
天賦基類:(就簡單點只用打印信息區(qū)分下好了)
public abstract class Talent {
// 只打印一下信息
public abstract void print();
}
兩個天賦實現(xiàn)類:
public class Talent_XiaGu extends Talent{
@Override
public void print() {
System.out.println("召喚師峽谷中的天賦");
}
}
public class Talent_ShenYuan extends Talent{
@Override
public void print() {
System.out.println("哭嚎深淵中的天賦");
}
}
召喚師技能基類:
public abstract class Skill {
// 召喚師技能種類
protected String[] skill_type;
// 選擇兩種召喚師技能
public void choose(int i, int j) {
System.out.println("你選擇了" + skill_type[i] + "和" + skill_type[j]);
}
}
兩個召喚師技能實現(xiàn)類:
public class Skill_XiaGu extends Skill {
public Skill_XiaGu() {
this.skill_type = new String[] { "閃現(xiàn)", "治療", "傳送", "凈化", "光盾", "虛弱",
"懲戒", "疾走" };
}
}
public class Skill_ShenYuan extends Skill {
public Skill_ShenYuan() {
this.skill_type = new String[] { "閃現(xiàn)", "治療", "雪球", "凈化", "光盾", "虛弱",
"回藍", "疾走" };
}
}
準備工作完畢,接下來就是重點了。
抽象工廠類或接口:
public interface AbstractFactory {
//創(chuàng)建英雄
public abstract Hero createHero();
//創(chuàng)建天賦
public abstract Talent createTalent();
//創(chuàng)建召喚師技能
public abstract Skill createSkill();
}
召喚師峽谷工廠類:
public class Factory_XiaGu implements AbstractFactory {
//假設我選艾希
public Hero createHero() {
return new Ashe_XiaGu();
}
public Talent createTalent() {
return new Talent_XiaGu();
}
public Skill createSkill() {
return new Skill_XiaGu();
}
}
哭嚎深淵工廠類:
public class Factory_ShenYuan implements AbstractFactory {
//假設我選艾希
public Hero createHero() {
return new Ashe_ShenYuan();
}
public Talent createTalent() {
return new Talent_ShenYuan();
}
public Skill createSkill() {
return new Skill_ShenYuan();
}
}
最后是客戶端代碼:
public class Client {
public static void main(String[] args) {
System.out.println("請選擇游戲模式");
System.out.println("1,召喚師峽谷 2,哭嚎深淵");
Scanner can = new Scanner(System.in);
int w = can.nextInt();
can.close();
AbstractFactory factory = null;
switch (w) {
case 1:
// 召喚師峽谷
factory = new Factory_XiaGu();
break;
case 2:
// 哭嚎深淵
factory = new Factory_ShenYuan();
break;
}
// 英雄(選擇的是艾希)
Hero hero = factory.createHero();
hero.print();
hero.say();
// 天賦
Talent talent = factory.createTalent();
talent.print();
// 召喚師技能
Skill skill = factory.createSkill();
skill.choose(0, 2);
}
}
客戶端選擇游戲模式,就相當于選擇了不同的工廠去生產(chǎn)游戲元素(英雄,天賦,召喚師技能)。
也可以結合工廠模式使用,比如選擇游戲類型后,利用工廠模式選擇英雄等等。
同工廠模式,客戶端不需要知道產(chǎn)品的創(chuàng)建過程。并且,客戶端只需要選擇游戲模式,就可以用工廠創(chuàng)建多個系列的產(chǎn)品(英雄,天賦,召喚師技能)。主要特點就是一個工廠多系列產(chǎn)品。
運行結果
玩局匹配,選召喚師峽谷:
源計劃皮膚的寒冰射手。
實際應用
常見的案例就是使用不同的數(shù)據(jù)庫,數(shù)據(jù)庫能處理用戶,也能處理關系。但是,數(shù)據(jù)庫分MySQL,Orical等。處理同樣或類似的事情,他們的具體實現(xiàn)存在差異。那就可以抽出一個工廠基類,再分別寫兩個不同的工廠去處理。這樣的話,某些東西就可以做到可遷移的目的。
附件
設計模式Demo
GitHub源碼:https://github.com/wzmyyj/Design-Pattern