設計模式之三:工廠方法模式—多型工廠的實現
阿新 • • 發佈:2018-12-31
簡單工廠的嚴重問題:
當系統中需要引進新產品時,靜態工廠方法通過所傳入引數的不同來建立不同的產品,這必定要修改工廠類的原始碼,違背了開閉原則
引入工廠方法模式:
針對不同的產品提供不同的工廠
定義:
定義一個用於建立物件的介面,讓子類決定將 哪一個類例項化,工廠方法迷失讓一個類例項化延遲到其子類,工廠方法模式又稱為工廠模式(Factory Pattern),又課稱作虛擬構造器模式(VIrtual Constructor Pattern)
一、工廠方法模式概述:
引入抽象工廠角色,可以是介面,也可以是抽象類或者具體類
程式碼:
interface Factory{
public Product factoryMethod();
}
class ConcreteFactory implements Factory{
public Product factoryMethod(){
return new COncreteFactory();
}
}
二、完整解決方案:
interface Logger{
public void writeLog();
}
class DatabaseLogger implements Logger{
public void writeLog(){
System.out.println("資料庫寫日誌");
}
}
class FileLogger implements Logger{
public void writeLog(){
System.out.println("檔案寫日誌");
}
}
interface LoggerFactory{
public Logger createLogger();
}
class DatabaseLoggerFactory implements Factory{
public Logger createLogger(){
Logger logger =new DatabaseLogger();
return logger();
}
}
class FileLoggerFactory implements Factory{
public Logger createLogger(){
Logger logger=new FileLogger();
return logger;
}
}
class Client{
public static void main(String[] args) {
LoggerFactory factory;
Logger logger;
factory=new FileLoggerFactory();
logger=factory.createLogger();
logger.writeLog()
}
}
三、反射與配置檔案
利用反射,返回xml中指定的物件,這樣修改就不用修改原始碼了。
<?xml version="1.0"?>
<config>
<chartType>histogram</chartType>
</config>
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;
class XMLUtil{
public static String getChartType(){
try{
DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();
DocumentBuilder builer=dFactory.newDocumentBuilder();
Document doc;
doc=builer.parse(new File("config.xml"));
NodeList nl=doc.getElementsByTagName("className");
Node classNode=nl.item(0).getFirstChild();
String cName=classNode.getNodeValue();
Class c=Class.forName(cName);
Object obj=c.newInstance();
return obj;
}
catch(Exception e){
e.printStackTrace();
return null;
}
}
}
Client端修改如下:
class Client{
public static void main(String[] args) {
LoggerFactory factory;
Logger logger;
factory=(LoggerFactory)XMLUtil.getBean;
logger=factory.createLogger();
logger.writeLog()
}
四、過載的工廠方法
使用工廠建立物件時,建立方法可以過載,使用args引數,obj引數,預設方式等多種引數來建立工廠
class DatabaseLoggerFactory implements Factory{
public Logger createLogger(){
Logger logger =new DatabaseLogger();
return logger();
}
public Logger createLogger(String args){
Logger logger =new DatabaseLogger();
return logger();
}
public Logger createLogger(Object obj){
Logger logger =new DatabaseLogger();
return logger();
}
}
五、工廠方法模式總結:
- 主要優點:
- 用火狐只需關心產品對應的工廠,無需關心建立細節,甚至具體產品的類的類名
- 多型,所有具體工廠類都具有同一個父類
- 加入新產品時,無需修改抽象工廠和抽象產品聽的介面,無需修改客戶端,也無需修改其他的具體工廠和具體產品,而指套新增一個具體工廠和具體產品就可以了,擴充套件性好
- 主要缺點:
- 新增新產品時徐太編寫新的具體產品類
- 為了擴充套件性,需要引入抽象層,增加系統的抽象性和理解難度,增加了實現的難度
- 適用場景:
- 客戶端不知道其所需要的物件的類
- 抽象工廠類通過其子類來指定建立那個物件