設計模式-工廠方法模式
阿新 • • 發佈:2021-01-16
概念
定義一個建立物件的介面,但讓實現這個介面的類來決定例項化哪個類,工廠方法讓類的例項化推遲到子類中進行.工廠方法模式又簡稱為工廠模式(Factory Pattern),又可稱作虛擬構造器模式(Virtual Constructor Pattern)或多型工廠模式(Polymorphic Factory Pattern)
應用場景
由於簡單工廠只提供一個工廠類來進行物件的建立,導致其職責過重,且程式碼不易維護,當系統需要擴充套件時,需要修改原有程式碼,導致違反了開閉原則,故引出工廠方法模式。如下情況可以考慮使用工廠方法模式
- 客戶端不知道它所需要的物件的類。在工廠方法模式中,客戶端不需要知道具體類名,只需要知道對應的工廠即可,具體的產品由具體工廠物件進行建立,可以將具體工廠類的類名儲存在配置檔案或者資料中,進行動態建立
具體應用
工廠方法模式就是利用了面向物件的多型性,提供抽象工廠型別,讓其實現類(具體工廠類)來決定要建立的具體物件
該模式主要包含如下角色:
- Factory(抽象工廠):在抽象工廠類中,聲明瞭一個建立方法,用於返回一個抽象產品
- ConcreteProduct(具體工廠):是抽象工廠的子類,實現了抽象工廠中定義的工廠方法,並可由客戶端呼叫,返回一個具體產品例項
- Product(抽象產品):定義產品的介面,是工廠方法所建立物件的公共父類
- ConcreteProduct(具體產品):實現了抽象產品介面,某種型別由專門的具體工廠進行建立,具體工廠和具體產品之間一一對應
程式碼實踐
還是繪製圖形,我們使用工廠方法模式來進行繪製圖形,並且增加了一個使用案例,即通過讀取配置檔案+反射的機制來實現執行時動態生成不同的物件。
/**
* 抽象產品類
* circular 圓形
* triangle 三角形
*/
public abstract class Graphical {
public abstract void draw();
public abstract void erase();
}
定義我們的具體產品,這裡具體的產品為三角形,和圓形。不支援方形
public class Circular extends Graphical { @Override public void draw() { System.out.println("畫了一個圓形"); } @Override public void erase() { System.out.println("擦掉了一個圓形"); } }
public class Triangle extends Graphical {
@Override
public void draw() {
System.out.println("畫了一個三角形");
}
@Override
public void erase() {
System.out.println("擦掉了一個三角形");
}
}
然後定義抽象工廠類GraphicalFactory
public interface GraphicalFactory {
public Graphical createGraphical();
}
定義具體工廠類,因為我們有2個具體產品(三角形和圓形),所以有2個具體工廠(CircularGraphicalFactory和TriangleGraphicalFactory)
//圓形工廠
public class CircularGraphicalFactory implements GraphicalFactory {
@Override
public Graphical createGraphical() {
return new Circular();
}
}
//三角形工廠
public class TriangleGraphicalFactory implements GraphicalFactory {
@Override
public Graphical createGraphical() {
return new Triangle();
}
}
定義通過配置檔案建立物件的工具類ConfigUtil
public class ConfigUtil {
public static Object getBean() {
try {
InputStream in = Test.class.getClassLoader().getResourceAsStream("Graphical.properties");
Properties props = new Properties();
InputStreamReader inputStreamReader = new InputStreamReader(in, "UTF-8");
props.load(inputStreamReader);
String cName=props.getProperty("factoryClassName");
//通過類名生成例項物件並將其返回
Class c=Class.forName(cName);
Object obj=c.newInstance();
return obj;
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
}
配置檔案 Graphical.properties
factoryClassName=com.donkeyx.pattern.factory.factorymethod.TriangleGraphicalFactory
測試類
public class Test {
public static void main(String[] args) {
System.out.println("---------------------------------使用預設方式進行建立----------------------------------");
defaultMethod();
System.out.println("---------------------------------讀取配置檔案方式進行動態建立----------------------------------");
readConfigFile();
}
/**
* 使用預設方式進行建立
*/
public static void defaultMethod(){
//建立一個圓形
GraphicalFactory factory;
factory = new CircularGraphicalFactory();
Graphical circular = factory.createGraphical();
circular.draw();
circular.erase();
//建立一個三角形
factory = new TriangleGraphicalFactory();
Graphical triangle = factory.createGraphical();
triangle.draw();
triangle.erase();
}
/**
* 讀取配置檔案方式進行動態建立
*/
public static void readConfigFile() {
GraphicalFactory factory;
factory = (GraphicalFactory)ConfigUtil.getBean();
Graphical graphical = factory.createGraphical();
graphical.draw();
graphical.erase();
}
}
結果
優點
- 在新產品加入時,無須修改抽象工廠和抽象產品的介面,無須修改客戶端,也無需修改其他的具體工廠和具體產品,只需要再加入一個具體工廠和具體產品就可以了,符合開閉原則,提高了系統的可擴充套件性
缺點
- 在新產品加入時,需要再加入一個具體工廠和具體產品,類的個數容易過多,增加了程式碼結構的複雜度
- 增加了系統的抽象性和理解難度