1. 程式人生 > >設計模式的藝術 工廠方法模式

設計模式的藝術 工廠方法模式

不懂使用為學過,說出用途,繪製結構為了解,不會靈活使用基本等於沒學。

前言

工廠方法模式是簡單工廠模式的延伸,它繼承了簡單工廠方法模式的優點,同時還彌補了簡單工廠方法模式的不足,

工廠方法模式是使用頻率最高的設計模式之一,是很多開源框架API類庫的核心模式

工廠方法模式的定義(Factory Method Pattern)

定義一個使用者建立物件的介面,讓子類決定將哪一個類例項化,工廠方法模式讓一個類的例項化延遲到其子類,工廠方法模式又被稱為工廠模式(Factory Pattern),有可以稱為虛擬構造器模式(Virtual Constructor Pattern)或者多型工廠模式(Polymorphic Factory Pattern)。工廠方法模式是一種類建立型模式

工廠方法模式的優點

(1)、在工廠方法模式中,工廠方法用來建立客戶所需要的產品,同時還隱藏了那個具體產品類將被例項化這一個實現細節,使用者只需要關注所需產品對應的工廠,無須關心建立細節,甚至無須知道具體產品類的類名

(2)、基於工廠角色和產品角色的多型性設計是工廠模式的關鍵,它能讓工廠可以自主確定建立何種產品物件,而如何建立這個物件的細節則完全封裝在具體工廠的內部,工廠方法模式又被稱之為多型工廠模式,正是因為所有的具體工廠類都具有同一個抽象父類

(3)、工廠方法模式最大的優勢在於系統新增產品時,無須修改抽象工廠和抽象產品提供的介面,只需要加上一個具體產品和對應的工廠即可,這樣子系統的擴充套件性也非常的好,完全符合了開閉原則

工廠方法模式的缺點

(1)、新增產品時,除了編寫新的具體產品類,還需要提供與之相對應的具體工廠類,這樣一定程度上增加了系統的複雜程度,有更多的類需要編譯和執行,會給系統帶來一些額外開銷

(2)、考慮到系統的可擴充套件性,會引入抽象層,在客戶端程式碼中皆使用抽象層定義,會增加系統的抽象性和理解難度,且在實現的時候可能需要用到DOM,反射技術,增加了系統的實現難度

工廠方法模式的應用場景

(1)、客戶端不需要知道其所需要的物件的類。因為在工廠方法模式中,客戶端不需要知道具體產品類的類名,只需知道對應工廠即可

(2)、抽象工廠通過其子類來確定建立哪個物件,在抽象工廠類中只需要提供一個建立產品的介面,而尤其子類來確定具體建立的物件,利用面向物件的多型性和里氏替換原則,在程式執行時,子類物件覆蓋父類物件,從而使系統更加容易擴充套件

工廠方法模式的具體實現

簡單的工廠模式的實現

Factory的介面

//工廠類的介面
public interface LoggerFactory {
    Logger createLogger();

}

Factory的具體實現

public class FileLoggerFactory implements LoggerFactory {
    @Override
    //具體產品
    public Logger createLogger() {
        Logger logger=new FileLogger();
        return  logger;
       }




}
public class DatabaseLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        Logger logger=new DatabaseLogger();
        return  logger;
    }


}

//輔助工具類,使用xml配置檔案和反射技術增加程式的擴充套件性

public class XMLUtil {
    public static Object getBean(){
        try {
            //建立DOC物件
            DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
            DocumentBuilder builder=builderFactory.newDocumentBuilder();
            Document document=builder.parse(new File(XMLUtil.class.getClassLoader().getResource("").getPath()+"config.xml"));
            //獲取包含類名的文字節點
            NodeList nodeList=document.getElementsByTagName("className");
            Node node =nodeList.item(0).getFirstChild();  //獲取第一位該節點值
            //通過類名生成例項物件並將其返回
            Class c=Class.forName(String.valueOf(node));
            Object o=c.newInstance();
            return o;

        }catch (Exception e){
            e.printStackTrace();
            return  null;
        }
    }
}

//所有產品的介面

//抽象產品
public interface Logger {
    void writeLog();
}

//產品的具體實現

public class FileLogger implements Logger {
    @Override
    public void writeLog() {
        System.out.println("檔案日誌記錄");
    }
}
public class DatabaseLogger implements Logger {
    @Override
    public void writeLog() {
        System.out.println("資料庫日誌記錄");
    }
}

//測試類

public class Main {

    public static void main(String[] args) {
       LoggerFactory loggerFactory;
       Logger logger;
       loggerFactory=(LoggerFactory)XMLUtil.getBean();  //返回OBJECT,需要強制轉換
        logger=loggerFactory.createLogger();
        logger.writeLog();

    }
}

轉載請註明出處,掌聲送給社會人