sincerit 簡單工廠模式(Simple Factory Pattern)
設計模式背後的思想:
面向介面程式設計而不是面向實現程式設計
優先使用組合而不是繼承
發現變化並且封裝變化—把有變化的抽象出來,抽象出來更加靈活
簡單工廠模式(Simple Factory Pattern)
簡單工廠模式:定義一個Factory類,Factory只有一個create方法,可以根據引數的不同返回不同類的例項,被建立的例項通常有共同的父類。
簡單工廠模式:只需要一個Factory類。
簡單工廠模式:又稱為靜態工廠模式(Static Factory Pattern),Factory類為靜態類或包含靜態方法。
簡單工廠模式:不屬於23種GOF設計模式,但在軟體開發中應用比較頻繁。
簡單工廠模式:實質是由一個工廠類根據傳入的引數,動態決定應該建立哪一個產品類例項。
簡單工廠模式結構圖
簡單工廠所包含的類:
Product: 抽象產品類,將具體產品類公共的程式碼進行抽象和提取後封裝在一個抽象產品類中。
ConcreteProduct:具體產品類,將需要建立的各種不同產品物件的相關程式碼封裝到具體產品類中。
Factory:工廠類,提供一個工廠類用於建立各種產品,在工廠類中提供一個建立產品的工廠方法,該方法可以根據所傳入引數的不同建立不同的具體產品物件。
Client:客戶端類,只需呼叫工廠類的工廠方法並傳入相應的引數即可得到一個產品物件。
程式碼如下:
Factory:
public class Factory {
//靜態工廠方法
public static Product createProduct(String type) {
Product product = null;
if (type.equals("ConcreteProductA")) {
product = new ConcreteProductA();
return product;
} else if (type.equals("ConcreteProductB")) {
product = new ConcreteProductB();
return product;
} // 等等其他的具體例項
return product;
}
}
Product:
public abstract class Product {
public abstract void disPlay();
// 等等具體類中公共的方法
}
ConcreteProduct:
public class ConcreteProductA extends Product {
@Override
public void disPlay() {
// 該類具體的邏輯業務,在這裡只顯示該類名稱
System.out.println("ConcreteProductA");
}
}
public class ConcreteProductB extends Product {
@Override
public void disPlay() {
// 該類具體的邏輯業務,在這裡只顯示該類名稱
System.out.println("ConcreteProductB");
}
}
Cilent:
public class Client {
public static void main(String[] args) {
String type = "ConcreteProductA";
Product product = Factory.createProduct(type);
product.disPlay();
}
}
方案改進:
由於每次建立一個例項要傳入一個String型別的type,但每更換一個物件時就要修改客戶端程式碼中type的值,客戶端要重新編譯,對於客戶而言,違反了開閉原則(對擴充套件開發對修改關閉),那麼有沒有一種不修改客戶端程式碼的前提下更換具體產品的物件呢?肯定是有的
可以將靜態工廠方法的引數儲存在XML或者properties格式的配置檔案中,如config.xml程式碼如下:
config.xml
<?xml version = "1.0">
<config>
<Type>ConcreteProductA</Type>
</config>
// 註明: 如果ConceteProductA有package則要寫上包名加上一個點 package.ConcreteProductA
client
public class Client {
public static void main(String[] args) {
String type = XMLUtil.getChartType(); // 通過配置檔案得到引數
Product product = Factory.createProduct(type); // 建立產品物件
product.disPlay();
}
}
XMLUtil
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XMLUtil {
public static String getChartType() {
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document;
document = documentBuilder.parse(new File("config.xml"));
NodeList nodeList = document.getElementsByTagName("Type");
Node classNode = nodeList.item(0).getFirstChild();
String chartType = classNode.getNodeValue();
return chartType;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
簡單工廠模式優點:
- 實現了建立物件和使用物件相分離
- Client無需知道所建立的ConcreteProduct類名,只需要知道ConcreteProduct所對應的引數
簡單工廠模式的缺點:
- 由於工廠類集中了所有產品的建立邏輯,職責過重。
- 系統擴充套件困難,一旦新增新的具體產品就不得不修改工廠邏輯(增加一個else if())
- 由於使用了靜態工廠方法,造成工廠角色無法形成基於繼承等級結構(靜態屬性和私有屬性不能被繼承)