在創建型模式中,工廠模式是我們日常使用最為頻繁的設計模式之一。工廠模式可細分為簡單工廠模式、工廠方法模式、抽象工廠模式。 簡單工廠模式 模式簡介 簡單工廠模式:根據參數返回不同類的實例,這些類通常具有共同的父類。 簡單工廠模式包括三個角色: 工廠 (Factory):用於創建所需產品,提供靜態工廠方 ...
在創建型模式中,工廠模式是我們日常使用最為頻繁的設計模式之一。工廠模式可細分為簡單工廠模式、工廠方法模式、抽象工廠模式。
簡單工廠模式
模式簡介
簡單工廠模式:根據參數返回不同類的實例,這些類通常具有共同的父類。
簡單工廠模式包括三個角色:
- 工廠 (Factory):用於創建所需產品,提供靜態工廠方法,返回抽象產品類型 Product;
- 抽象產品 (Product):是工廠創建的所有對象的父類,封裝了各種共有方法;
- 具體產品 (ConcreateProduct):工廠創建目標,繼承抽象產品,實現了抽象產品的抽象方法。
應用實例
-
工廠——FruitFactory
public class FruitFactory { public static Object createFruit(String clazzName) throws Exception{ Object obj = null; if (clazzName.equals(Apple.class.getName())){ obj = new Apple(); } else if (clazzName.equals(Strawberry.class.getName())){ obj = new Strawberry(); } else if (clazzName.equals(Banana.class.getName())){ obj = new Banana(); } else { throw new ClassNotFoundException("沒有找到該類"); } return obj; } //升級簡化版 /*public static Object create(String clazzName) throws Exception{ Object obj = null; Class clazz = Class.forName(clazzName); if (clazz.isAssignableFrom(Fruit.class)){ obj = clazz.newInstance(); } else { throw new ClassNotFoundException("沒有找到該類"); } return obj; }*/ }
-
抽象產品——Fruit
public abstract class Fruit { public abstract void getInfo(); }
-
具體產品——Apple、Banana、Strawberry
- Apple
public class Apple extends Fruit{ @Override public void getInfo() { System.out.println("這是一個砸中牛頓腦袋的蘋果"); } }
- Banana
public class Banana extends Fruit{ @Override public void getInfo() { System.out.println("這是一根讓猶太人致富的香蕉"); } }
- Strawberry
public class Strawberry extends Fruit{ @Override public void getInfo() { System.out.println("這是一顆甜到你心裡的草莓"); } }
-
客戶端
public class MainTest { public static void main(String[] args) throws Exception { //要個蘋果 Apple apple = (Apple) FruitFactory.createFruit(Apple.class.getName()); apple.getInfo(); //要顆草莓 Strawberry strawberry = (Strawberry) FruitFactory.createFruit(Strawberry.class.getName()); strawberry.getInfo(); //要根香蕉 Banana banana = (Banana) FruitFactory.createFruit(Banana.class.getName()); banana.getInfo(); } }
模式總結
優點:實現簡單,屏蔽了對象創建過程,實現了對象創建和使用的分離。
缺點:集中了所有產品創建邏輯,職責過重;擴展困難,一旦添加類需修改源碼;使用靜態工廠方法,工廠角色無法形成繼承結構。
使用場景:工廠負責創建對象較少。
工廠方法模式
模式簡介
工廠方法模式:定義了一個用於創建對象的介面,但是讓子類決定將哪個類實例化。工廠方法讓一個類的實例化延遲到了子類。
工廠方法模式在簡單工廠模式的基礎上,引入了抽象工廠,將具體產品的創建延遲到了具體工廠,剋服了簡單工廠模式職責過重的缺點。
工廠方法模式包括了 4 個角色:
- 抽象工廠(AbstractFactory):定義了抽象工廠方法,用於返回一個產品,具體返回哪類產品由具體工廠決定。
- 抽象產品(AbstractProduct):是所有具體產品的公共父類,定義了產品的介面。
- 具體工廠(ConcreteFactory):是抽象工廠的子類,實現了抽象工廠的工廠方法,返回一個具體產品。
- 具體產品(ConcreteProduct):實現了抽象產品介面,由具體工廠創建。
應用實例
-
抽象工廠——FruitFactory
public abstract class FruitFactory { public abstract Fruit createFruit(); }
-
抽象產品——Fruit
public abstract class Fruit { public abstract void getInfo(); }
-
具體工廠——AppleFactory、BananaFactory、StrawberryFactory
- AppleFactory
public class AppleFactory extends FruitFactory{ @Override public Fruit createFruit() { return new Apple(); } }
- BananaFactory
public class BananaFactory extends FruitFactory{ @Override public Fruit createFruit() { return new Banana(); } }
- StrawberryFactory
public class StrawberryFactory extends FruitFactory{ @Override public Fruit createFruit() { return new Strawberry(); } }
-
具體產品——Apple、Banana、Strawberry
- Apple
public class Apple extends Fruit { @Override public void getInfo() { System.out.println("這是一個砸中牛頓腦袋的蘋果"); } }
- Banana
public class Banana extends Fruit { @Override public void getInfo() { System.out.println("這是一根讓猶太人致富的香蕉"); } }
- Strawberry
public class Strawberry extends Fruit { @Override public void getInfo() { System.out.println("這是一顆甜到你心裡的草莓"); } }
-
客戶端
public class MainTest { public static void main(String[] args) throws Exception { FruitFactory factory = null; //要個蘋果 factory = new AppleFactory(); Fruit apple = factory.createFruit(); apple.getInfo(); //要顆草莓 factory = new StrawberryFactory(); Fruit strawberry = factory.createFruit(); strawberry.getInfo(); //要根香蕉 factory = new BananaFactory(); Fruit banana = factory.createFruit(); banana.getInfo(); } }
模式總結
優點
- 隱藏了對象創建細節,用戶創建對象時無需知道具體類名,只需知道相應的工廠類即可創建相應類對象。
- 在系統中添加新的產品時不會對現有代碼產生影響,具有良好的擴展性,符合開閉原則。
缺點
- 每個產品需要添加對應的具體工廠類,類的數量因此成對增加,增加了系統複雜性和性能消耗。
- 引入了抽象層,增加了系統的抽象性和理解難度。
使用場景
- 客戶端不需要知道它所需創建的類對象的類名;
- 抽象類通過子類來指定創建具體哪個類的對象。
抽象工廠模式
模式簡介
抽象工廠:提供一個創建一系列相關或相關以來對象的介面,從而無需指定他們具體的類。
兩個概念
產品等級結構:即產品的繼承結構,水果是個抽象類,其子類包括蘋果、香蕉、草莓,則抽象類與具體類之間構成了一個產品等級結構。
產品族:在抽象工廠模式中,產品族是同一個工廠生產的不同產品等級結構中的一組產品。例如當前有兩個生產水果的工廠A和B都生產水果蘋果、香蕉、草莓,則工廠A生產的蘋果、香蕉、草莓構成一個產品族。
抽象工廠模式與工廠方法模式的區別在於,工廠方法模式針對的是一個產品等級結構,每一個具體工廠只能創建一個產品;而抽象工廠模式針對的是多個產品等級結構,其每個具體工廠負責創建一族的產品。
抽象工廠模式包括了 4 個角色:
- 抽象工廠(AbstractFactory):聲明瞭一組用於創建一族產品的方法,每個方法對應一種產品。
- 抽象產品(AbstractProduct):為每種產品聲明介面,在抽象產品中聲明瞭產品所具有的業務方法。
- 具體工廠(ConcreteFactory):實現了抽象工廠中聲明的創建產品的方法,生成了一組具體產品,這些具體產品構成了一個產品族,每個產品位於某個產品等級結構中。
- 具體產品(ConcreteProduct):實現了抽象產品介面,由具體工廠創建。
應用實例
-
抽象工廠——FruitFactory
public abstract class FruitFactory { public abstract Fruit createApple(); public abstract Fruit createBanana(); public abstract Fruit createStrawberry(); }
-
抽象產品
public abstract class Fruit { public abstract void getInfo(); }
-
具體工廠——FruitFactoryA、FruitFactoryB
- FruitFactoryA
public class FruitFactoryA extends FruitFactory { @Override public Fruit createApple() { return new AppleA(); } @Override public Fruit createBanana() { return new BananaA(); } @Override public Fruit createStrawberry() { return new StrawberryA(); } }
- FruitFactoryB
public class FruitFactoryB extends FruitFactory { @Override public Fruit createApple() { return new AppleB(); } @Override public Fruit createBanana() { return new BananaB(); } @Override public Fruit createStrawberry() { return new StrawberryB(); } }
-
具體產品AppleA、AppleB、BananaA、BananaB、StrawberryA、StrawberryB
- AppleA
public class AppleA extends Fruit { @Override public void getInfo() { System.out.println("這是一個砸中牛頓腦袋的蘋果,由工廠A生產"); } }
- AppleB
public class AppleB extends Fruit { @Override public void getInfo() { System.out.println("這是一個砸中牛頓腦袋的蘋果,由工廠B生產"); } }
- BananaA
public class BananaA extends Fruit { @Override public void getInfo() { System.out.println("這是一根讓猶太人致富的香蕉,由工廠A生產"); } }
- BananaB
public class BananaB extends Fruit { @Override public void getInfo() { System.out.println("這是一根讓猶太人致富的香蕉,由工廠B生產"); } }
- StrawberryA
public class StrawberryA extends Fruit { @Override public void getInfo() { System.out.println("這是一顆甜到你心裡的草莓,由工廠A生產"); } }
- StrawberryB
public class StrawberryB extends Fruit { @Override public void getInfo() { System.out.println("這是一顆甜到你心裡的草莓,由工廠B生產"); } }
-
客戶端
public class MainTest { public static void main(String[] args) throws Exception { FruitFactory factoryA = new FruitFactoryA(); FruitFactory factoryB = new FruitFactoryA(); //要個蘋果 Fruit appleA = factoryA.createApple(); appleA.getInfo(); Fruit appleB = factoryB.createApple(); appleB.getInfo(); //要顆草莓 Fruit strawberryA = factoryA.createStrawberry(); strawberryA.getInfo(); Fruit strawberryB = factoryA.createStrawberry(); strawberryB.getInfo(); //要根香蕉 Fruit bananaA = factoryA.createStrawberry(); bananaA.getInfo(); Fruit bananaB = factoryA.createStrawberry(); bananaB.getInfo(); } }
模式總結
優點
- 隔離了具體類的生成,更換一個具體工廠就可以在某種程度上改變整個軟體系統行為。
- 當一個產品族的多個對象被設計成一起工作時,能夠保證客戶始終只是用同一個產品族中的對象。
- 添加新的產品無需修改已有代碼,符合開閉原則。
缺點
- 添加新的產品等級結構需要對原有系統進行較大修改,違背了開閉原則。
使用場景
- 系統有過個產品族,而每次使用只使用其中一個產品族;
- 產品等級結構穩定,設計完成後不會對系統增加或刪除的產品等級結構。
工廠模式總結
- 簡單工廠模式隱藏了對象創建細節,將象創建過程與系統業務分離,只需傳入響應參數即可獲得相應對象,缺點是職責過重。
- 工廠方法模式引入了抽象工廠,剋服了簡單工廠模式的缺點,將具體對象創建延遲到了子類且可以靈活擴展,但一定程度上造成了系統的類數量膨脹,損耗系統性能。
- 抽象工廠模式在工廠方法模式的基礎上進一步擴展,每個具體工廠負責創建多個產品等級結構,減小了工廠方法模式造成的類膨脹問題,提供了系統效率。但是,抽象工廠模式存在開閉原則的傾向性,適用於只需擴展產品族,而產品登記結構穩定的系統。