基於上圖說的場景,咱們瞭解全部的英雄和英雄皮膚均可以被購買,那麼咱們先定義一個接口讓全部英雄和英雄皮膚遵循這個規則java
public interface Hero { /** * 成功購買英雄 */ void buyHeroSuccess(); /** * 成功購買配套皮膚 */ void buySkinSuccess(); }
那麼接下來咱們開始定義不一樣的英雄,這裏咱們分別選 妲己、程咬金、后羿 做爲示例ide
/** * 妲己 */ public class DaJi implements Hero { @Override public void buyHeroSuccess() { System.out.println("勇士,恭喜你得到了英雄-妲己!"); } @Override public void buySkinSuccess() { System.out.println("恭喜你得到了皮膚-熱情桑巴"); } }
/** * 程咬金 */ public class ChengYaoJin implements Hero { @Override public void buyHeroSuccess() { System.out.println("勇士,恭喜你得到了英雄-程咬金!"); } @Override public void buySkinSuccess() { System.out.println("恭喜你得到了皮膚-愛與正義"); } }
/** * 后羿 */ public class HouYi implements Hero { @Override public void buyHeroSuccess() { System.out.println("勇士,恭喜你得到了英雄-后羿!"); } @Override public void buySkinSuccess() { System.out.println("恭喜你得到了皮膚-黃金射手座"); } }
上面咱們一會兒就定義了三個英雄,下面就能夠開始簡單工廠的核心了-工廠測試
既然是工廠模式,那麼生產產品的時候(即建立類),由工廠統一管理,咱們經過標籤去決定生產什麼樣的產品3d
/** * 王者榮耀工廠(商城) */ public class HerosFactory { /** * 根據不一樣的標籤生產不一樣的英雄 */ public Hero getDifferentHero(String heroType) { if("HouYi".equals(heroType)){ return new HouYi(); }else if("DaJi".equals(heroType)){ return new DaJi(); }else if("ChengYaoJin".equals(heroType)){ return new ChengYaoJin(); } return null; } }
寫完了簡單工廠的工廠類,咱們能夠寫個測試方法測試一下code
/** * 測試方法 */ public class TestFactory { public static void main(String[] args) { HerosFactory herosFactory = new HerosFactory(); Hero hero1 = herosFactory.getDifferentHero("DaJi"); hero1.buyHeroSuccess(); hero1.buySkinSuccess(); System.out.println("-----------------"); Hero hero2 = herosFactory.getDifferentHero("HouYi"); hero2.buyHeroSuccess(); hero2.buySkinSuccess(); } }
我我的認爲工廠方法模式是簡單工廠模式的升級,咱們先想一想簡單工廠模式最大的缺點是啥?對象
若是我想新增一個對象,那麼我就須要擴展工廠類,即我須要去改工廠類的生產方法代碼去增長一個標籤blog
這麼幹,實際違背了 開閉原則-對外擴展開放,對內修改關閉
比較好的方案是什麼呢?繼承
再定義一個抽象的工廠類型的基類,讓子類去實現該基類(也就是工廠與實例對象遙相呼應),可能這麼說,仍是有人不明白,上代碼
接口
首先英雄接口部分仍是和簡單工廠一致get
public interface Hero { /** * 成功購買英雄 */ void buyHeroSuccess(); /** * 成功購買配套皮膚 */ void buySkinSuccess(); }
接着咱們是已購買三個英雄,妲己、程咬金、后羿
/** * 妲己 */ public class DaJi implements Hero { @Override public void buyHeroSuccess() { System.out.println("勇士,恭喜你得到了英雄-妲己!"); } @Override public void buySkinSuccess() { System.out.println("恭喜你得到了皮膚-熱情桑巴"); } }
/** * 程咬金 */ public class ChengYaoJin implements Hero { @Override public void buyHeroSuccess() { System.out.println("勇士,恭喜你得到了英雄-程咬金!"); } @Override public void buySkinSuccess() { System.out.println("恭喜你得到了皮膚-愛與正義"); } }
/** * 后羿 */ public class HouYi implements Hero { @Override public void buyHeroSuccess() { System.out.println("勇士,恭喜你得到了英雄-后羿!"); } @Override public void buySkinSuccess() { System.out.println("恭喜你得到了皮膚-黃金射手座"); } }
上述代碼都是和簡單工廠部分一致,針對咱們說的問題,咱們說 定義一個抽象的工廠類型的基類
/** * 工廠方法模式:(王者榮耀商城) */ public abstract class HeroFactory { protected abstract Hero productHero(); }
咱們已經看到了,基類的抽象方法能夠建立英雄,那麼須要建立的子類工廠經過繼承該基類就能夠完成建立所需英雄的功能了
/** * 定義一個射手英雄工廠 */ public class ArrowFactory extends HeroFactory{ @Override protected Hero productHero() { return new HouYi(); } }
/** * 法師工廠 */ public class MageFactory extends HeroFactory{ @Override protected Hero productHero() { return new DaJi(); } }
/** * 坦克工廠 */ public class TanksFactory extends HeroFactory{ @Override protected Hero productHero() { return new ChengYaoJin(); } }
定義完三個工廠,咱們再次進行測試
/** * 測試工廠方法模式 */ public class TestFatcoryMethod { public static void main(String[] args) { Hero hero1 = new ArrowFactory().productHero(); hero1.buyHeroSuccess(); hero1.buySkinSuccess(); System.out.println("------------"); Hero hero2 = new MageFactory().productHero(); hero2.buyHeroSuccess(); hero2.buySkinSuccess(); } }
抽象工廠模式是全部形態的工廠模式中最爲抽象和最具通常性的一種形態模式。(否則怎麼叫抽象工廠)
其次抽象工廠是指當有多個抽象角色,使用一種工廠模式。抽象工廠能夠向提供一個接口,使客戶端在不指定產品的具體狀況下,建立多個產品族中的對象。一個抽象工廠類,能夠派生多個具體工廠類,每一個具體的工廠類能夠建立多個產品的實例。
工廠方法模式 是對 一個產品類型進行構建,而抽象工廠則針對的 是 多個產品類型的構建。
下面咱們用代碼去演繹抽象工廠模式:
以前說過王者榮耀商城中,能夠買英雄和皮膚。按照面向對象的思想咱們能夠將英雄 和 皮膚 單獨抽取,成爲最頂層的接口。那麼會有下面的代碼:
//英雄的頂層接口 public interface Hero { void haveHero(); }
定義完第一個抽象角色,也就是英雄的頂層接口,接下來咱們定義具體的實現
/** * 妲己 */ public class DaJiHero implements Hero { @Override public void haveHero() { System.out.println("勇士,恭喜你已得到-妲己"); } }
/** * 程咬金 */ public class ChengYaoJinHero implements Hero { @Override public void haveHero() { System.out.println("勇士,恭喜你已得到-程咬金"); } }
/** * 后羿 */ public class HouYiHero implements Hero { @Override public void haveHero() { System.out.println("勇士,恭喜你得到了英雄-后羿"); } }
咱們知道英雄還有皮膚,因此咱們定義第二個抽象角色,即皮膚的頂層接口
/** * 皮膚 */ public interface Skin { void haveSkin(); }
接着定義皮膚接口的實現類
/** * 妲己皮膚 */ public class DaJiSkin implements Skin{ @Override public void haveSkin() { System.out.println("恭喜你得到了皮膚-熱情桑巴"); } }
/** * 程咬金皮膚 */ public class ChengYaoJinSkin implements Skin { @Override public void haveSkin() { System.out.println("恭喜你得到了皮膚-愛與正義"); } }
/** * 后羿皮膚 */ public class HouYiSkin implements Skin{ @Override public void haveSkin() { System.out.println("恭喜你得到了皮膚-黃金射手座"); } }
根據上面的概念,咱們定義完了2個抽象角色,那麼還需定義一個抽象工廠。可能你會問爲何要定義一個抽象工廠,由於上面的概念也說到了定義抽象工廠的目的就是爲了派生具體的工廠類(也就是讓子類去實現)。這個抽象工廠類加上abstract 關鍵字後,又該如何去寫內部的邏輯,我想這一塊纔是最須要思考和解決的問題。
/** * 商品工廠(頂層多態接口 ) */ public interface MarketFactory { }
/** * 英雄抽象工廠 */ public abstract class HeroAbStractFactory implements MarketFactory { public abstract Hero getHero(String heroType); }
/** * 皮膚抽象工廠 */ public abstract class SkinAbStractFactory implements MarketFactory { public abstract Skin getSkin(String skinType); }
定義完抽象工廠,咱們實現兩個工廠
/** * 英雄工廠 */ public class HeroFactory extends HeroAbStractFactory { @Override public Hero getHero(String heroType) { if("HouYi".equals(heroType)){ return new HouYiHero(); }else if("DaJi".equals(heroType)){ return new DaJiHero(); }else if("ChengYaoJin".equals(heroType)){ return new ChengYaoJinHero(); } return null; } }
/** * 皮膚工廠 */ public class SkinFactory extends SkinAbStractFactory { @Override public Skin getSkin(String skinType) { if("HouYi".equals(skinType)){ return new HouYiSkin(); }else if("DaJi".equals(skinType)){ return new DaJiSkin(); }else if("ChengYaoJin".equals(skinType)){ return new ChengYaoJinSkin(); } return null; } }
那麼,咱們已經定義完具體的實例工廠,一個是英雄工廠,一個是皮膚工廠,如今能夠定義一個統一管理類管理這兩個工廠
/** * 工廠(商城) */ public class FactoryProduct { public static MarketFactory getFactoryByType(String factoryType){ if("HeroFactory".equals(factoryType)){ return new HeroFactory(); }else if("SkinFactory".equals(factoryType)){ return new SkinFactory(); } return null; } }
最後咱們開始測試
/** * 工廠測試 */ public class TestFactory { public static void main(String[] args) { HeroFactory heroFactory = (HeroFactory) FactoryProduct.getFactoryByType("HeroFactory"); Hero hero = heroFactory.getHero("ChengYaoJin"); hero.haveHero(); SkinFactory skinFactory = (SkinFactory) FactoryProduct.getFactoryByType("SkinFactory"); Skin skin = skinFactory.getSkin("ChengYaoJin"); skin.haveSkin(); } }