1. 工廠方法模式
使用場景
- 工廠方法模式是new一個對象的替代品,所以在所有需要生成對象的地方都可以使用,到那時需要慎重考慮是否要增加一個工廠類進行管理,增加代碼的復(fù)雜度。
- 需要靈活的、可擴展的框架時,可以考慮采用工廠方法模式。
- 工廠方法模式可以用在異構(gòu)項目中。
- 可以使用在測試驅(qū)動開發(fā)的框架下。
定義
定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。
下面是工廠方法模式的通用類圖:
通用類圖
優(yōu)點
-
良好的封裝性,代碼結(jié)構(gòu)清晰
一個對象創(chuàng)建是有條件約束的,如一個調(diào)用者需要一個具體的產(chǎn)品對象,只要知道這個產(chǎn)品的類名(或約束字符串)就可以了,不用知道創(chuàng)建對象的艱辛過程,降低模塊間的耦合。 -
工廠方法模式的擴展性非常優(yōu)秀
在增加產(chǎn)品類的情況下,只要適當?shù)匦薷木唧w的工廠類或擴展一個工廠類,就可以完成“擁抱變化”。 -
屏蔽產(chǎn)品類
這一點非常重要,產(chǎn)品類的實現(xiàn)如何變化,調(diào)用者都不需要關(guān)系,它只需要關(guān)心產(chǎn)品的接口,只要接口保持不變,系統(tǒng)中的上層模塊就不要發(fā)生變化。因為產(chǎn)品類的實例化工作是由工廠類負責的,一個產(chǎn)品對象具體由哪一個產(chǎn)品生成是由工廠類決定的。 -
工廠方法模式是典型的解耦框架
高層模塊只需要知道產(chǎn)品的抽象類,其他的實現(xiàn)類都不用關(guān)心,符合迪米特法則,我不需要的就不要去交流;也符合依賴倒置原則,只依賴產(chǎn)品類的抽象;當然也符合里氏替換原則,使用產(chǎn)品子類替換父類也沒問題。
具體實現(xiàn)
- 抽象產(chǎn)品類
/**
* 抽象產(chǎn)品類
*
*/
public abstract class Product {
// 產(chǎn)品類的公共方法
public void method1() {
// 業(yè)務(wù)處理邏輯
System.out.println("這是所有產(chǎn)品共有的方法!");
}
// 抽象方法
public abstract void method2();
}
- 具體產(chǎn)品類
具體產(chǎn)品1
/**
* 具體產(chǎn)品類1
*
*/
public class ConcreteProduct1 extends Product {
@Override
public void method2() {
System.out.println("產(chǎn)生了具體產(chǎn)品一!");
}
}
具體產(chǎn)品2
/**
* 具體產(chǎn)品類2
*
*/
public class ConcreteProduct2 extends Product {
@Override
public void method2() {
System.out.println("產(chǎn)生了具體產(chǎn)品二!");
}
}
- 抽象工廠類
/**
* 抽象工廠類
*
*/
public abstract class Creator {
/**
* 創(chuàng)建一個產(chǎn)品對象,其輸入?yún)?shù)類型可以自行設(shè)置
* 通常為String、Enum、Class等,當然也可以為空
* @param <T>
* @param c
* @return
*/
public abstract <T extends Product> T createProduct(Class<T> c);
}
- 具體工廠類
/**
* 具體工廠類
*
*/
public class ConcreteCreator extends Creator {
@Override
public <T extends Product> T createProduct(Class<T> c) {
Product product = null;
try {
product = (Product) Class.forName(c.getName()).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return (T) product;
}
}
- 測試類
/**
* 客戶類
*
*/
public class testCreator {
/**
* @param args
*/
public static void main(String[] args) {
Creator creator = new ConcreteCreator();
Product product1 = creator.createProduct(ConcreteProduct1.class);
Product product2 = creator.createProduct(ConcreteProduct2.class);
/*
* 繼續(xù)業(yè)務(wù)處理
*/
product1.method1();
product1.method2();
product2.method1();
product2.method2();
}
}
2. 抽象工廠模式
使用場景
一個對象族(或是一組沒有任何關(guān)系的對象)都有相同的約束,則可以使用抽象工廠模式。
定義
為創(chuàng)建一組相關(guān)或相互依賴的對象提供一個接口,而且無需指定它們的具體類。
抽象工廠模式是工廠方法模式的升級版本,在有多個業(yè)務(wù)品種、業(yè)務(wù)分類時,通過抽象工廠模式產(chǎn)生需要的對象是一種非常好的解決方式。
通用類圖如下:
抽象工廠類圖
優(yōu)缺點
優(yōu)點:
- 封裝性。
每個產(chǎn)品的實現(xiàn)類不是高層模塊要關(guān)心的,高層模塊只關(guān)心抽象和接口,不關(guān)心對象是如何創(chuàng)建出來的。 - 產(chǎn)品族內(nèi)的約束為非公開狀態(tài)。
具體的產(chǎn)品族內(nèi)的約束是在工廠內(nèi)實現(xiàn)的。
缺點:
- 抽象工廠模式的最大缺點就是產(chǎn)品族擴展非常困難。
例如增加產(chǎn)品C,也就是說產(chǎn)品家族由原來2個增加到3個,抽象類AbstractFactory要增加一個方法createProductC(),然后兩個實現(xiàn)類都要修改。
具體實現(xiàn)
- 抽象產(chǎn)品類
抽象產(chǎn)品類A
/**
* 抽象產(chǎn)品類A
*
*/
public abstract class AbstractProductA {
public void shareMethod(){
System.out.println("這是共享的產(chǎn)品A方法!");
}
public abstract void doSomething();
}
抽象產(chǎn)品類B
/**
* 抽象產(chǎn)品類B
*
*/
public abstract class AbstractProductB {
public void shareMethod(){
System.out.println("這是共享的產(chǎn)品B方法!");
}
public abstract void doSomething();
}
- 具體產(chǎn)品類
具體產(chǎn)品A1
/**
* 具體產(chǎn)品類A1
*
*/
public class ProductA1 extends AbstractProductA {
@Override
public void doSomething() {
System.out.println("這是產(chǎn)品A1");
}
}
具體產(chǎn)品A2
/**
* 具體產(chǎn)品類A2
*
*/
public class ProductA2 extends AbstractProductA {
@Override
public void doSomething() {
System.out.println("這是產(chǎn)品A2");
}
}
具體產(chǎn)品B1
/**
* 具體產(chǎn)品類B1
*
*/
public class ProductB1 extends AbstractProductB {
@Override
public void doSomething() {
System.out.println("這是產(chǎn)品B1");
}
}
具體產(chǎn)品B2
/**
* 具體產(chǎn)品類B2
*
*/
public class ProductB2 extends AbstractProductB {
@Override
public void doSomething() {
System.out.println("這是產(chǎn)品B2");
}
}
- 抽象工廠類
/**
* 抽象工廠類
*
*/
public abstract class AbstractFactory {
public abstract AbstractProductA createProductA();
public abstract AbstractProductB createProductB();
}
- 具體工廠類
具體工廠類1(產(chǎn)生X1系列產(chǎn)品)
/**
* 具體工廠類1
*
*/
public class Factory1 extends AbstractFactory {
@Override
public AbstractProductA createProductA() {
// TODO Auto-generated method stub
return new ProductA1();
}
@Override
public AbstractProductB createProductB() {
// TODO Auto-generated method stub
return new ProductB1();
}
}
具體工廠類2(產(chǎn)生X2系列產(chǎn)品)
/**
* 具體工廠類2
*
*/
public class Factory2 extends AbstractFactory {
@Override
public AbstractProductA createProductA() {
// TODO Auto-generated method stub
return new ProductA2();
}
@Override
public AbstractProductB createProductB() {
// TODO Auto-generated method stub
return new ProductB2();
}
}
- 測試類
/**
* 客戶類
*
*/
public class testAbstractFactory {
/**
* @param args
*/
public static void main(String[] args) {
// 定義出兩個工廠
AbstractFactory factory1 = new Factory1();
AbstractFactory factory2 = new Factory2();
// 產(chǎn)生A1對象
AbstractProductA a1 = factory1.createProductA();
// 產(chǎn)生A2對象
AbstractProductA a2 = factory2.createProductA();
// 產(chǎn)生B1對象
AbstractProductB b1 = factory1.createProductB();
// 產(chǎn)生B2對象
AbstractProductB b2 = factory2.createProductB();
// 業(yè)務(wù)處理
a1.shareMethod();
a1.doSomething();
a2.shareMethod();
a2.doSomething();
b1.shareMethod();
b1.doSomething();
b2.shareMethod();
b2.doSomething();
}
}