【設(shè)計模式】抽象工廠模式

設(shè)計模式

抽象工廠模式

抽象工廠模式(Abstract Factory Pattern)是所有形態(tài)的工廠模式中最為抽象和最具一般性的一種形態(tài)。抽象工廠模式是指當(dāng)有多個抽象角色時,使用的一種工廠模式。抽象工廠模式可以向客戶端提供一個接口,使客戶端在不必指定產(chǎn)品的具體的情況下,創(chuàng)建多個產(chǎn)品族中的產(chǎn)品對象。

UML類圖

抽象工廠模式
  1. 抽象產(chǎn)品類(AbstractProductX):多個系列抽象產(chǎn)品(X=A,B,C...)。
  2. 具體產(chǎn)品類(ProductX):實(shí)現(xiàn)基類中的抽象方法(多個不同的具體產(chǎn)品,X=1,2,3..)。
  3. 抽象工廠類或接口(AbstractFactory):定義具體工廠的多個公共接口(擁有各系列產(chǎn)品創(chuàng)建的接口)。
  4. 具體工廠類(FactoryX):定義創(chuàng)建各系列具體產(chǎn)品實(shí)例的方法。(每個工廠對應(yīng)一種具體產(chǎn)品,X=1,2,3...)。

與工廠模式的區(qū)別

  1. 工廠模式的工廠只能生產(chǎn)一個系列的產(chǎn)品。而抽象工廠模式的工廠可以生產(chǎn)一個或多個系列的產(chǎn)品。
  2. 工廠模式關(guān)注的是一個系列的不同種產(chǎn)品。而抽象工廠模式關(guān)注的是不同系列產(chǎn)品。

案例分析

接著上篇【設(shè)計模式】工廠模式的話題。

場景:玩《英雄聯(lián)盟》(5v5 moba端游)新開一局游戲,游戲開始每個玩家需要選一個英雄之外,還需要選擇天賦,召喚師技能。也就是需要創(chuàng)建三種產(chǎn)品。并且,在不同玩法下,比如召喚師峽谷(自選或排位等)與哭嚎深淵(大亂斗),創(chuàng)建的產(chǎn)品也略微有所差異,比如大亂斗下英雄一開始就3級,召喚師技能沒有傳送,有雪球。結(jié)構(gòu)上:

  1. 產(chǎn)品(三個系列):英雄,天賦,召喚師技能。
  2. 工廠(兩個):召喚師峽谷工廠,哭嚎深淵工廠。

代碼實(shí)現(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 {
    // 簡化構(gòu)造方法,只弄個名字。
    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;
    }
}

天賦基類:(就簡單點(diǎn)只用打印信息區(qū)分下好了)

public abstract class Talent {
    // 只打印一下信息
    public abstract void print();
}

兩個天賦實(shí)現(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]);
    }
}

兩個召喚師技能實(shí)現(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)", "治療", "雪球", "凈化", "光盾", "虛弱",
                "回藍(lán)", "疾走" };
    }
}

準(zhǔn)備工作完畢,接下來就是重點(diǎ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 {
    //假設(shè)我選艾希
    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 {
    //假設(shè)我選艾希
    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);

    }

}

客戶端選擇游戲模式,就相當(dāng)于選擇了不同的工廠去生產(chǎn)游戲元素(英雄,天賦,召喚師技能)。

也可以結(jié)合工廠模式使用,比如選擇游戲類型后,利用工廠模式選擇英雄等等。

工廠模式,客戶端不需要知道產(chǎn)品的創(chuàng)建過程。并且,客戶端只需要選擇游戲模式,就可以用工廠創(chuàng)建多個系列的產(chǎn)品(英雄,天賦,召喚師技能)。主要特點(diǎn)就是一個工廠多系列產(chǎn)品。

運(yùn)行結(jié)果

玩局匹配,選召喚師峽谷:


控制臺

源計劃皮膚的寒冰射手。


源計劃-艾希

實(shí)際應(yīng)用

常見的案例就是使用不同的數(shù)據(jù)庫,數(shù)據(jù)庫能處理用戶,也能處理關(guān)系。但是,數(shù)據(jù)庫分MySQL,Orical等。處理同樣或類似的事情,他們的具體實(shí)現(xiàn)存在差異。那就可以抽出一個工廠基類,再分別寫兩個不同的工廠去處理。這樣的話,某些東西就可以做到可遷移的目的。

附件

設(shè)計模式Demo
GitHub源碼:https://github.com/wzmyyj/Design-Pattern

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容