將實例化對象的代碼提取出來,放到一個類中統一管理和維護,達到和主項目的依賴關係的解耦。從而提升項目的擴展和維護性。工廠模式都是實現建立者和調用者分離,下面開始逐一介紹:程序員
工廠角色(Creator) | 是簡單工廠模式的核心,它負責實現建立全部具體產品類的實例。工廠類能夠被外界直接調用,建立所需的產品對象。 |
抽象產品角色(Product) | 是全部具體產品角色的父類,它負責描述全部實例所共有的公共接 口 。 |
具體產品角色(Concrete Product) | 繼承自抽象產品角色,通常爲多個,是簡單工廠模式的建立目標。工廠類返回的都是該角色的某一具體產品。 |
package Factory; interface Car{ void run(); } class Aodi implements Car{ @Override public void run() { System.out.println("我是奧迪汽車..."); } } class Benchi implements Car{ @Override public void run() { System.out.println("我是奔馳汽車..."); } } class CarFactory{ static public Car createCar(String name) { Car car = null; if(name.equals("奧迪")) { car = new Aodi(); }else if(name.equals("奔馳")) { car = new Benchi(); } return car; } } /** * @author Moti * @Time 2019年9月21日 */ public class Main { public static void main(String[] args) { Car car = CarFactory.createCar("奔馳"); car.run(); } }
工廠類是整個模式的關鍵.包含了必要的邏輯判斷,根據外界給定的信息,決定究竟應該建立哪一個具體類的對象.經過使用工廠類,外界能夠從直接建立具體產品對象的尷尬局面擺脫出來,僅僅須要負責「消費」對象就能夠了。而沒必要管這些對象究竟如何建立及如何組織的.明確了各自的職責和權利,有利於整個軟件體系結構的優化。ide
因爲工廠類集中了全部實例的建立邏輯,違反了高內聚責任分配原則,將所有建立邏輯集中到了一個工廠類中;它所能建立的類只能是事先考慮到的,若是須要添加新的類,則就須要改變工廠類了。違反開閉原則 。性能
當系統中的具體產品類不斷增多時候,可能會出現要求工廠類根據不一樣條件建立不一樣實例的需求.這種對條件的判斷和對具體產品類型的判斷交錯在一塊兒,很難避免模塊功能的蔓延,對系統的維護和擴展很是不利;優化
這些缺點在工廠方法模式中獲得了必定的克服。this
每個產品都有本身獨立的工廠設計
抽象產品(Product) | 具體產品的父類 描述具體產品的公共接口 |
具體產品(Concrete Product) | 抽象產品的子類;工廠類建立的目標類 描述生產的具體產品 |
抽象工廠(Factory) | 具體工廠的父類 描述具體工廠的公共接口 |
具體工廠(Concrete Factory) | 抽象工廠的子類;被外界調用描述具體工廠;實現FactoryMethod工廠方法建立產品的實例 |
1. 汽車的抽象類3d
package AbstractFactory; /** * 定義汽車的抽象類 * @author Moti * @Time 2019年9月27日 下午3:04:23 */ public abstract class Car { public abstract void run(); }
2. 奧迪汽車類code
package AbstractFactory; /** * 定義奧迪車,繼承抽象類Car實現run方法 * @author Moti * @Time 2019年9月27日 下午3:06:10 */ public class Aodi extends Car { @Override public void run() { System.out.println("我是奧迪車..滴滴滴.."); } }
3. 奔馳汽車類對象
package AbstractFactory; /** * 定義奔馳車,繼承抽象類Car實現run方法 * @author Moti * @Time 2019年9月27日 下午3:07:29 */ public class Benchi extends Car { @Override public void run() { System.out.println("我是奔馳車..滴滴滴.."); } }
4. 抽象汽車工廠的接口blog
package AbstractFactory; /** * 汽車工廠的接口,將具體實例的生成交給子類 * @author Moti * @Time 2019年9月27日 下午3:08:35 */ public interface CarFactory { Car createCar(); }
5. 奧迪汽車工廠的類,實現了抽象汽車工廠接口
package AbstractFactory; /** * 定義奧迪車的工廠 * @author Moti * @Time 2019年9月27日 下午3:09:53 */ public class AodiCarFactory implements CarFactory { @Override public Car createCar() { return new Aodi(); } }
6. 奔馳汽車工廠的類,實現了抽象汽車工廠接口
package AbstractFactory; /** * 定義奔馳車的工廠 * @author Moti * @Time 2019年9月27日 下午3:10:57 */ public class BenchiCarFactory implements CarFactory { @Override public Car createCar() { return new Benchi(); } }
7. 客戶端調用
package AbstractFactory; /** * @author Moti * @Time 2019年9月27日 下午3:12:45 */ public class Client { public static void main(String[] args) { CarFactory carFactory1 = new AodiCarFactory(); CarFactory carFactory2 = new BenchiCarFactory(); Car car1 = carFactory1.createCar(); Car car2 = carFactory2.createCar(); car1.run(); car2.run(); } }
用戶只須要關心所需產品對應的工廠,無需關心建立細節,甚至無需知道具體產品類名;全部的具體工廠類都具備同一抽象父類;符合開閉原則,新增產品只須要添加工廠類和具體產品,無需修改代碼,擴展性好;
添加一個新的產品,系統中類的個數增長,致使增長了系統的複雜性,有更多的類須要編譯和運行,會增長系統性能的開銷;因爲考慮到系統的可擴展性,須要引入抽象層,在客戶端代碼中均使用抽象層進行定義,增長了系統的抽象性和理解難度;
產品等級:產品等級結構即產品的繼承結構,如一個抽象類是電視機,其子類有海爾電視機、海信電視機、TCL電視機,則抽象電視機與具體品牌的電視機之間構成了一個產品等級結構,抽象電視機是父類,而具體品牌的電視機是其子類。
產品族:在抽象工廠模式中,產品族是指由同一個工廠生產的,位於不一樣產品等級結構中的一組產品,如海爾電器工廠生產的海爾電視機、海爾電冰箱,海爾電視機位於電視機產品等級結構中,海爾電冰箱位於電冰箱產品等級結構中,海爾電視機、海爾電冰箱構成了一個產品族。
這裏,1號工廠(ConcreteFactory1)能夠生產A,B,C三種產品(ConcreteProductA,B,C)
一樣,2號工廠也能夠生產A,B,C三種產品
那麼1號工廠生產的這三種產品構成一個產品族,2號工廠生產的這三種產品也構成一個產品族.
1號工廠生產的A產品和2號工廠生產的A產品構成一個產品等級
1號工廠生產的B產品和2號工廠生產的B產品 構成一個產品等級
1號工廠生產的C產品和2號工廠生產的C產品 構成一個產品等級
抽象產品(Product) | 具體產品的父類 描述具體產品的公共接口 |
具體產品(Concrete Product) | 抽象產品的子類;工廠類建立的目標類 描述生產的具體產品 |
抽象工廠(Factory) | 具體工廠的父類 描述具體工廠的公共接口 |
具體工廠(Concrete Factory) | 抽象工廠的子類;被外界調用描述具體工廠;實現抽象工廠中建立產品的實例 |
注意:這裏日本工廠生產的全部產品構成一個產品族,中國工廠生產的全部產品也構成一個產品族,共兩個產品族.示例程序中出現了兩種RAM,兩種CPU,兩種Mouse(分別來自中國工廠和日本工廠),這些同種商品分類構成一個產品等級,也就是說有三個產品等級.
1.抽象產品和具體產品
//設備接口(產品的抽象) public interface Device { String getDeviceName(); } //RAM(具體的產品) public class RAM implements Device { private String factoryName; public RAM(String factoryName) { this.factoryName = factoryName; } @Override public String getDeviceName() { return "得到"+factoryName+"生產的RAM"; } } //CPU(具體的產品) public class CPU implements Device { private String factoryName; public CPU(String factoryName) { this.factoryName = factoryName; } @Override public String getDeviceName() { return "得到"+factoryName+"生產的CPU"; } } //Mouse(具體的產品) public class Mouse implements Device { private String factoryName; public Mouse(String factoryName) { this.factoryName = factoryName; } @Override public String getDeviceName() { return "得到"+factoryName+"生產的Mouse"; } }
2.抽象工廠和具體工廠
//抽象工廠 public interface DeviceFactory { Device createCPU(); Device createARM(); Device createMouse(); } //具體工廠 public class ChinaFactoy implements DeviceFactory { @Override public Device createCPU() { return new CPU("中國"); } @Override public Device createARM() { return new RAM("中國"); } @Override public Device createMouse() { return new Mouse("中國"); } } //具體工廠 public class JapanFactory implements DeviceFactory{ @Override public Device createCPU() { return new CPU("日本"); } @Override public Device createARM() { return new RAM("日本"); } @Override public Device createMouse() { return new Mouse("日本"); } }
3.客戶端Client
public class Client { public static void main(String[] args) { DeviceFactory factory = new JapanFactory(); Device device = factory.createMouse(); String string = device.getDeviceName(); System.out.println(string); } }
分離了具體的類。客戶經過抽象接口操縱實例,產品的類名也在具體工廠的實現中被分離,它們不出如今客戶代碼中。
易於交換產品系列。一個具體工廠類只在初始化時出現一次,這使得改變一個應用的具體工廠變得很容易,只需改變具體的工廠便可使用不一樣的產品配置。
有利於產品的一致性。當一個系列的產品對象被設計成一塊兒工做時,一個應用一次只能使用同一個系列中的對象,這一點很重要,而抽象工廠很容易實現這一點。
難以支持新種類的產品。由於抽象工廠接口肯定了能夠被建立的產品集合(產品族),因此難以擴展抽象工廠以生產新種類的產品。