工廠方法模式

工廠方法模式

概念

是一種常用的類創建型設計模式,此模式的核心精神是封裝類中變化的部分,提取其中個性化善變的部分爲獨立類,通過依賴注入以達到解耦、複用和方便後期維護拓展的目的。

角色

  • 抽象產品
    工廠方法模式所創建的對象的超類型,也就是產品對象的共同父類或共同擁有的接口。
  • 具體產品
    這個角色實現了抽象產品角色所定義的接口。某具體產品有專門的具體工廠創建,它們之間往往一一對應。
  • 抽象工廠
    是工廠方法模式的核心,與應用程序無關。任何在模式中創建的對象的工廠類必須實現這個接口。
  • 具體工廠
    這是實現抽象工廠接口的具體工廠類,包含與應用程序密切相關的邏輯,並且受到應用程序調用以創建產品對象

UML圖如下

簡單工廠模式的優缺點

優點

  • 用工廠創建客戶所需產品,向客戶隱藏了具體是哪個產品被實例化,客戶只需關心哪個工廠創建那個產品而不需要關心創建細節
  • 讓工廠自主確定創建何種產品,如何創建完全封裝在具體工廠內部
  • 符合開閉原則,向系統中添加新產品只需要添加具體的工廠和產品即可

缺點

  • 添加新產品需要編寫具體產品類以及與之對應的工廠類,類的個數成對增加

適合環境

  • 客戶端不需要知道他所需要對象的類
  • 對於某個產品,客戶端清楚地知道應該使用哪個具體工廠服務

例子

現需要一個日誌記錄器可以通過多種方式來保存日誌,例如文件系統和數據庫系統,用戶只需通過修改配置文件就可以靈活的切換日誌方式,並且在設計日誌記錄器時,開發人員系統對日誌記錄器做一系列初始化工作,並且初始化參數設置極爲複雜。

分析

我們先將實體與簡單工廠的角色一一對應

  • 抽象產品: Logger
  • 具體產品: DatabaseLogger,FileLogger
  • 抽象工廠: LoggerFactory
  • 具體工廠: DatabaseLoggerFactory,FileLoggerFactory

看不懂不要緊,我們先看UML圖,在看代碼應該就能理解了
在這裏插入圖片描述

編碼

Logger.java

package cn.kevinlu98.factorymethod;

/**
 * @Author: Kevin·Lu
 * @Date: 9:02 PM 2019/7/25
 * @Description: 日誌記錄器接口,充當抽象產品角色
 */
public interface Logger {
    public void writeLog();
}

FileLogger.java

package cn.kevinlu98.factorymethod;

/**
 * @Author: Kevin·Lu
 * @Date: 9:06 PM 2019/7/25
 * @Description: 文件日誌記錄器,充當具體的產品角色
 */
public class FileLogger implements Logger {
    @Override
    public void writeLog() {
        System.out.println("文件日誌記錄");
    }
}

DatabaseLogger.java

package cn.kevinlu98.factorymethod;

/**
 * @Author: Kevin·Lu
 * @Date: 9:04 PM 2019/7/25
 * @Description: 數據庫日誌記錄器,充當具體產品角色
 */
public class DatabaseLogger implements Logger {
    @Override
    public void writeLog() {
        System.out.println("數據庫日誌記錄");
    }
}

LoggerFactory.java

package cn.kevinlu98.factorymethod;

/**
 * @Author: Kevin·Lu
 * @Date: 9:07 PM 2019/7/25
 * @Description: 日誌記錄器工廠接口,充當抽象工廠角色
 */
public interface LoggerFactory {
    /**
     * 抽象工廠方法
     *
     * @return
     */
    public Logger createLogger();
}

FileLoggerFactory.java

package cn.kevinlu98.factorymethod;

/**
 * @Author: Kevin·Lu
 * @Date: 9:11 PM 2019/7/25
 * @Description: 文件日誌記錄器工廠類,充當具體工廠角色
 */
public class FileLoggerFactory implements LoggerFactory {

    @Override
    public Logger createLogger() {
        //創建文件日誌記錄器對象
        Logger logger = new FileLogger();
        //創建文件,代碼略
        return logger;
    }
}

DatabaseLoggerFactory.java

package cn.kevinlu98.factorymethod;

/**
 * @Author: Kevin·Lu
 * @Date: 9:09 PM 2019/7/25
 * @Description: 數據庫日誌記錄器工廠類,充當具體工廠角色
 */
public class DatabaseLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        //連接數據庫,代碼略
        //創建數據庫日誌記錄器對象
        Logger logger = new DatabaseLogger();
        //初始化數據庫日誌記錄器,代碼略
        return logger;
    }
}

config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<config>
    <className>cn.kevinlu98.factorymethod.DatabaseLoggerFactory</className>
</config>

XMLUtil.xml

package cn.kevinlu98.factorymethod;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;

/**
 * @Author: Kevin·Lu
 * @Date: 9:17 PM 2019/7/25
 * @Description: 讀取xml文件中的字符串參數
 */
public class XMLUtil {
    public static Object getBean() {
        try {
            //創建dom文檔對象
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new File("src/cn/kevinlu98/factorymethod/config.xml"));

            //獲取包含類名的文本節點
            NodeList nl = document.getElementsByTagName("className");
            Node classNode = nl.item(0).getFirstChild();
            String name = classNode.getNodeValue();
            //通過類名生成實例對象並將其返回
            Class c = Class.forName(name);
            Object object = c.newInstance();
            return object;

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

    }
}

Client.java

package cn.kevinlu98.factorymethod;

/**
 * @Author: Kevin·Lu
 * @Date: 9:12 PM 2019/7/25
 * @Description: 工廠方法設計模式 客戶端測試
 */
public class Client {
    public static void main(String[] args) {
//        LoggerFactory factory = (LoggerFactory) XMLUtil.getBean();
        LoggerFactory factory = new DatabaseLoggerFactory();
        Logger logger = factory.createLogger();
        logger.writeLog();
    }
}

運行結果

至此,工廠方法設計模式介紹完成,希望能幫助到您

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章