工廠模式能夠將對象的創建和使用解耦,且當創建一個對象的過程繁雜時,又有大量地方需要重複創建該對象,使用工廠模式則可以降低代碼的重複率。另外,將對象的創建封裝到工廠類,當創建過程發生改變時,可直接修改工廠類,而無需到每個創建對象的地方修改代碼,降低了系統的維護成本。
目錄
一、簡單工廠模式
1.定義
又稱靜態工廠模式,該模式定義一個專門的類負責實例的創建,被創建的實例通常有相同的父類。
2.角色:
- Factory:工廠類,根據參數的不同創建不同的實例
- Product:抽象產品類
- ConcreteProduct:具體產品類
3.特點
- 優點:將對象的創建和對象本身業務處理分離,降低系統耦合度。
- 缺點:因爲對象的創建交由工廠處理,當產品種類過多時,需要修改工廠方法,不符合開閉原則,且將使得工廠方法邏輯複雜,不易於維護和擴展。
4.示例
產品接口:
public interface Product {
void say();
}
具體產品類:
// ConcreteProductA
public class ConcreteProductA implements Product {
@Override
public void say() {
System.out.println("I'm Product A.");
}
}
// ConcreteProductB
public class ConcreteProductB implements Product {
@Override
public void say() {
System.out.println("I'm Product B.");
}
}
工廠類:
public class Factory {
public static Product createProduct(String arg) {
if (arg == "A")
return new ConcreteProductA();
else if (arg == "B")
return new ConcreteProductB();
return null;
}
}
測試類:
public class TestSimpleFactory {
public static void main(String[] args) {
Product productA = Factory.createProduct("A");
Product productB = Factory.createProduct("B");
productA.say();
productB.say();
}
}
// 輸出
// I'm Product A.
// I'm Product B.
二、工廠方法模式
1.定義
定義了一個創建對象的接口,但由子類決定要實例化的對象是哪一個,該模式讓類把實例化推遲到子類。
2.角色
- Product:抽象產品類
- ConcreteProduct:具體產品類
- Factory:抽象工廠類
- ConcreteFactory:具體工廠類
3.特點
- 優點:實例的創建延遲到子類執行,由子類來確定創建何種實例,當有新產品加入時,只需要添加一個新工廠和新產品而無需修改現有系統。
- 缺點:因爲產品和工廠是成對增加,一定程度上增加了系統的複雜度。
4.示例
產品接口及具體產品類同上
工廠接口:
public interface Factory {
Product createProduct();
}
具體工廠接口:
// ConcreteFactoryA
public class ConcreteFactoryA implements Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
// ConcreteFactoryB
public class ConcreteFactoryB implements Factory {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
測試類:
public class TestFactoryMethod {
public static void main(String[] args) {
Factory factoryA = new ConcreteFactoryA();
Factory factoryB = new ConcreteFactoryB();
Product productA = factoryA.createProduct();
Product productB = factoryB.createProduct();
productA.say();
productB.say();
}
}
// 輸出
// I'm Product A.
// I'm Product B.
三、抽象工廠類
1.定義
提供一個接口,用於創建相關或依賴對象的家族,而不需要明確指定具體類。
2.角色
- AbstractProduct:抽象產品類
- ConcreteProduct:具體產品類
- AbstractFactory:抽象工廠類
- ConcreteFactory:具體工廠類
3.特點
- 優點:可通過具體工廠類創建產品族的多個對象。
- 缺點:其開閉原則具有傾斜性,即增加或者修改產品族比較方便,可直接增加新的具體工廠和產品族,但增加新的產品等級結構很複雜,需要修改抽象工廠和所有的具體工廠類。
4.示例
產品接口及其具體產品類:
// AbstractProductA
public interface AbstractProductA {
void use();
}
// AbstractProductB
public interface AbstractProductB {
void eat();
}
// ProductA1
public class ProductA1 implements AbstractProductA {
@Override
public void use() {
System.out.println("I'm using ProductA1.");
}
}
// ProductA2
public class ProductA2 implements AbstractProductA {
@Override
public void use() {
System.out.println("I'm using ProductA2.");
}
}
// ProductB1
public class ProductB1 implements AbstractProductB {
@Override
public void eat() {
System.out.println("I'm eating ProductB1.");
}
}
// ProductB2
public class ProductB2 implements AbstractProductB {
@Override
public void eat() {
System.out.println("I'm eating ProductB2.");
}
}
工廠接口及其具體工廠類:
// Factory
public interface Factory {
AbstractProductA createProductA();
AbstractProductB createProductB();
}
// ConcreteFactory1
public class ConcreteFactory1 implements Factory {
@Override
public AbstractProductA createProductA() {
return new ProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ProductB1();
}
}
// ConcreteFactory2
public class ConcreteFactory2 implements Factory {
@Override
public AbstractProductA createProductA() {
return new ProductA2();
}
@Override
public AbstractProductB createProductB() {
return new ProductB2();
}
}
測試類:
public class TestAbstractFactory {
public static void main(String[] args) {
Factory factory1 = new ConcreteFactory1();
AbstractProductA productA1 = factory1.createProductA();
AbstractProductB productB1 = factory1.createProductB();
productA1.use();
productB1.eat();
Factory factory2 = new ConcreteFactory2();
AbstractProductA productA2 = factory2.createProductA();
AbstractProductB productB2 = factory2.createProductB();
productA2.use();
productB2.eat();
}
}
// 輸出
// I'm using ProductA1.
// I'm eating ProductB1.
// I'm using ProductA2.
// I'm eating ProductB2.
參考:
1.《Head First 設計模式》
2.圖說設計模式 https://design-patterns.readthedocs.io/zh_CN/latest/index.html