自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

最簡單的設(shè)計模式,抽象工廠模式,是否屬于過度設(shè)計?

開發(fā) 前端
新增具體產(chǎn)品時,擴展新的工廠類再在客戶端中創(chuàng)建工廠類代碼 和 在客戶端中直接創(chuàng)建實例代碼,有什么本質(zhì)區(qū)別嗎?

在日常開發(fā)中,我們往往忽視了設(shè)計模式的重要性。這可能是因為項目時間緊迫,或者對設(shè)計模式理解不深。其實,很多時候我們可能在不經(jīng)意間已經(jīng)使用了某些模式。

重要的是要有意識地學(xué)習(xí)和應(yīng)用,讓代碼更加優(yōu)雅和高效。也許是時候重新審視我們的編程實踐,將設(shè)計模式融入其中了。

先從最簡單的設(shè)計模式【抽象工廠模式】走起,讓我們一起“重學(xué)設(shè)計模式”。

靈魂拷問:新增具體產(chǎn)品時,擴展新的工廠類再在客戶端中創(chuàng)建工廠類代碼 和 在客戶端中直接創(chuàng)建實例代碼,有什么本質(zhì)區(qū)別嗎?

一、不采用抽象工廠模式

假設(shè)你正在設(shè)計一套系統(tǒng),該系統(tǒng)用于創(chuàng)建不同配置的電腦,例如PC和服務(wù)器。每種類型的電腦都有不同的CPU和內(nèi)存。

1.抽象產(chǎn)品

/**
 * 抽象產(chǎn)品 - CPU
 */
public interface CPU {

    void compute();
}

/**
 * 抽象產(chǎn)品 - 內(nèi)存
 */
public interface Memory {

    void store();
}

2.具體產(chǎn)品

/**
 * 具體產(chǎn)品 - PC 的 CPU 實現(xiàn)
 */
public class PCCPU implements CPU {

    @Override
    public void compute() {
        System.out.println("PC CPU is computing");
    }
}

/**
 * 具體產(chǎn)品 - PC 的內(nèi)存實現(xiàn)
 */
public class PCMemory implements Memory {

    @Override
    public void store() {
        System.out.println("PC Memory is storing data");
    }
}

/**
 * 具體產(chǎn)品 - 服務(wù)器的 CPU 實現(xiàn)
 */
public class ServerCPU implements CPU {

    @Override
    public void compute() {
        System.out.println("Server CPU is computing with high performance");
    }
}

/**
 * 具體產(chǎn)品 - 服務(wù)器的內(nèi)存實現(xiàn)
 */
public class ServerMemory implements Memory {

    @Override
    public void store() {
        System.out.println("Server Memory is storing data with high capacity");
    }
}

3.測試類 ~ 不用抽象工廠模式

/**
 * 不用抽象工廠模式
 */
public class Client {
    public static void main(String[] args) {
        // 創(chuàng)建 PC 的組件
        CPU pcCPU = new PCCPU();
        Memory pcMemory = new PCMemory();
        pcCPU.compute();
        pcMemory.store();

        // 創(chuàng)建 服務(wù)器 的組件
        CPU serverCPU = new ServerCPU();
        Memory serverMemory = new ServerMemory();
        serverCPU.compute();
        serverMemory.store();
    }
}

4.新增筆記本的CPU和內(nèi)存

/**
 * 具體產(chǎn)品 - 新增筆記本電腦的 CPU 實現(xiàn)
 */
public class LaptopCPU implements CPU {

    @Override
    public void compute() {
        System.out.println("Laptop CPU is computing efficiently");
    }
}

/**
 * 具體產(chǎn)品 - 筆記本電腦的內(nèi)存實現(xiàn)
 */
public class LaptopMemory implements Memory {

    @Override
    public void store() {
        System.out.println("Laptop Memory is storing data efficiently");
    }
}

5.在Client測試類中新增:

// 創(chuàng)建筆記本的
CPU laptopCPU = new LaptopCPU();
laptopCPU.compute();
LaptopMemory laptopMemory = new LaptopMemory();
laptopMemory.store();

還是很方便的。

二、那么,如果采用抽象工廠模式優(yōu)化上面代碼,要怎么做呢?

抽象工廠模式(Abstract Factory Pattern)是一種創(chuàng)建型設(shè)計模式,旨在提供一個接口,用于創(chuàng)建相關(guān)或依賴對象的家族,而無需指定它們的具體類。通過抽象工廠模式,客戶端可以通過接口創(chuàng)建一系列相關(guān)對象,而無需知道這些對象的具體實現(xiàn)。

抽象工廠模式通常包括以下幾個部分:

  • 抽象工廠接口(Abstract Factory):定義創(chuàng)建產(chǎn)品的接口。
  • 具體工廠類(Concrete Factory):實現(xiàn)抽象工廠接口,生成具體的產(chǎn)品。
  • 抽象產(chǎn)品接口(Abstract Product):定義產(chǎn)品的接口。
  • 具體產(chǎn)品類(Concrete Product):實現(xiàn)具體的產(chǎn)品。
  • 客戶端(Client):通過工廠接口來使用產(chǎn)品,而不依賴于具體產(chǎn)品的實現(xiàn)。

1.抽象工廠接口

/**
 * 抽象工廠
 */
public interface ComputerFactory {

    CPU createCPU();

    Memory createMemory();
}

2.具體工廠類

/**
 * 具體工廠 - PC 工廠
 */
public class PCFactory implements ComputerFactory {

    @Override
    public CPU createCPU() {
        return new PCCPU();
    }

    @Override
    public Memory createMemory() {
        return new PCMemory();
    }
}

/**
 * 具體工廠 - 服務(wù)器工廠
 */
public class ServerFactory implements ComputerFactory {

    @Override
    public CPU createCPU() {
        return new ServerCPU();
    }

    @Override
    public Memory createMemory() {
        return new ServerMemory();
    }
}

3.測試類 ~ 抽象工廠模式

public class AbstractFactoryClient {

    public static void main(String[] args) {
        // 使用 PC 工廠創(chuàng)建 PC 組件
        ComputerFactory pcFactory = new PCFactory();
        CPU pcCPU = pcFactory.createCPU();
        Memory pcMemory = pcFactory.createMemory();

        pcCPU.compute();
        pcMemory.store();

        // 使用服務(wù)器工廠創(chuàng)建服務(wù)器組件
        ComputerFactory serverFactory = new ServerFactory();
        CPU serverCPU = serverFactory.createCPU();
        Memory serverMemory = serverFactory.createMemory();

        serverCPU.compute();
        serverMemory.store();
    }
}

使用抽象工廠模式時,新增筆記本電腦,如何實現(xiàn)?

4.新增筆記本電腦的具體工廠類

public class LaptopFactory implements ComputerFactory {

    @Override
    public CPU createCPU() {
        return new LaptopCPU();
    }

    @Override
    public Memory createMemory() {
        return new LaptopMemory();
    }
}

5.在測試類中新增

// 使用筆記本工廠
ComputerFactory laptopFactory = new LaptopFactory();
CPU laptopCPU = laptopFactory.createCPU();
Memory laptopMemory = laptopFactory.createMemory();

laptopCPU.compute();
laptopMemory.store();

三、新增具體產(chǎn)品時,擴展新的工廠類再在客戶端中創(chuàng)建工廠類代碼 和 在客戶端中直接創(chuàng)建實例代碼,有什么本質(zhì)區(qū)別嗎?

1.解耦

問題:  在不使用抽象工廠模式的實現(xiàn)中,客戶端代碼(Client)直接依賴于具體的產(chǎn)品類(如 PCCPU、PCMemory、ServerCPU 等)。當(dāng)需要增加新類型的電腦或更改現(xiàn)有的電腦配置時,客戶端代碼必須修改。

抽象工廠模式引入了工廠接口(ComputerFactory),客戶端通過工廠接口創(chuàng)建對象,而不是直接實例化具體類。這樣客戶端與具體的產(chǎn)品實現(xiàn)解耦,客戶端不需要知道具體的產(chǎn)品類名,只需要依賴工廠接口。代碼更加靈活,可以支持不同的產(chǎn)品家族(PC、服務(wù)器、筆記本、工作站等)而無需修改客戶端代碼。

產(chǎn)品創(chuàng)建邏輯都集中在具體工廠中,客戶端只關(guān)心如何使用產(chǎn)品,而不關(guān)心它們是如何創(chuàng)建的。

2.擴展性

問題: 如果要在不使用工廠模式的代碼中增加一個新產(chǎn)品(例如,平板電腦的CPU和內(nèi)存),需要修改客戶端代碼,增加新產(chǎn)品的實例化邏輯。這違反了開閉原則(對擴展開放,對修改關(guān)閉)。

抽象工廠模式允許我們通過創(chuàng)建新的工廠(例如 LaptopFactory)來生成新產(chǎn)品,而無需修改客戶端代碼。只需在新工廠中提供相應(yīng)的產(chǎn)品(CPU和Memory),然后將工廠傳遞給客戶端。

支持開閉原則:新增產(chǎn)品只需增加新的工廠類,不需要修改已有代碼,減少了風(fēng)險和維護成本。

方便維護:如果產(chǎn)品發(fā)生變化(比如某種CPU規(guī)格變動),只需要在工廠中修改,不必修改所有調(diào)用代碼,系統(tǒng)的靈活性顯著提高。

3.單一職責(zé)原則

問題:  客戶端代碼不僅負(fù)責(zé)業(yè)務(wù)邏輯,還負(fù)責(zé)產(chǎn)品的創(chuàng)建邏輯,違反了單一職責(zé)原則。

在客戶端中創(chuàng)建工廠類:客戶端的職責(zé)更加單一,只負(fù)責(zé)業(yè)務(wù)邏輯處理,產(chǎn)品的創(chuàng)建則完全由工廠負(fù)責(zé)。通過將產(chǎn)品的創(chuàng)建與使用分離,代碼變得更加清晰、職責(zé)分明。

優(yōu)點:遵循單一職責(zé)原則,產(chǎn)品創(chuàng)建邏輯集中在工廠中,客戶端只處理與產(chǎn)品的使用有關(guān)的業(yè)務(wù)邏輯。

四、在jdk源碼中,哪些地方應(yīng)用了抽象工廠模式

在 JDK 的源碼中,抽象工廠模式被廣泛應(yīng)用于創(chuàng)建不同類型的對象家族。

一個典型的例子是 javax.xml.parsers.DocumentBuilderFactory 和 javax.xml.parsers.SAXParserFactory,它們都是 JDK 中使用抽象工廠模式的具體實現(xiàn)。這些工廠用于創(chuàng)建與 XML 解析相關(guān)的對象,如 DocumentBuilder 和 SAXParser,而客戶端不需要關(guān)心這些對象的具體實現(xiàn)。

1.DocumentBuilderFactory 在 JDK 中的應(yīng)用

(1)抽象工廠類:DocumentBuilderFactory

DocumentBuilderFactory 是一個抽象工廠,用于創(chuàng)建 DocumentBuilder,它負(fù)責(zé)解析 XML 文檔。

newInstance() 方法會返回一個具體的工廠實現(xiàn)(如 org.apache.xerces.jaxp.DocumentBuilderFactoryImpl),該工廠實現(xiàn)負(fù)責(zé)創(chuàng)建具體的 DocumentBuilder 對象。

package javax.xml.parsers;

public abstract class DocumentBuilderFactory {
    // 用于創(chuàng)建 DocumentBuilder 實例
    public abstract DocumentBuilder newDocumentBuilder() throws ParserConfigurationException;

    // 工廠方法,用于獲取 DocumentBuilderFactory 的實例
    public static DocumentBuilderFactory newInstance() {
        return FactoryFinder.find(DocumentBuilderFactory.class, "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
    }
}

(2)具體工廠類:DocumentBuilderFactoryImpl

DocumentBuilderFactoryImpl 是 DocumentBuilderFactory 的一個具體實現(xiàn),它定義了如何創(chuàng)建 DocumentBuilder。

newDocumentBuilder() 返回一個 DocumentBuilderImpl 實例,具體負(fù)責(zé)解析 XML。

package org.apache.xerces.jaxp;

public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory {

    @Override
    public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
        return new DocumentBuilderImpl();
    }
}

(3)客戶端使用

在客戶端代碼中,使用 DocumentBuilderFactory 創(chuàng)建 DocumentBuilder 對象,而不需要關(guān)心具體實現(xiàn)。

通過 DocumentBuilderFactory.newInstance(),客戶端獲取了一個具體的 DocumentBuilderFactory 實例,然后使用該工廠創(chuàng)建 DocumentBuilder 對象。

客戶端不關(guān)心 DocumentBuilder 的具體實現(xiàn),只依賴于抽象工廠接口,符合抽象工廠模式的設(shè)計思想。

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class XMLParserExample {
    public static void main(String[] args) {
        try {
            // 獲取 DocumentBuilderFactory 實例(抽象工廠)
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            
            // 使用工廠創(chuàng)建 DocumentBuilder(具體產(chǎn)品)
            DocumentBuilder builder = factory.newDocumentBuilder();
            
            // 使用 DocumentBuilder 解析 XML 文檔
            // 示例代碼忽略了具體 XML 文件的解析邏輯
            System.out.println("DocumentBuilder created successfully!");
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.SAXParserFactory 的應(yīng)用

SAXParserFactory 是 JDK 中另一個典型的抽象工廠模式實現(xiàn),它用于創(chuàng)建 SAXParser 對象,解析 XML 文檔。

(1)抽象工廠類:SAXParserFactory

SAXParserFactory 是抽象工廠類,定義了創(chuàng)建 SAXParser 的方法。

package javax.xml.parsers;

public abstract class SAXParserFactory {
    // 創(chuàng)建 SAXParser 的抽象方法
    public abstract SAXParser newSAXParser() throws ParserConfigurationException, SAXException;

    // 獲取 SAXParserFactory 實例
    public static SAXParserFactory newInstance() {
        return FactoryFinder.find(SAXParserFactory.class, "org.apache.xerces.jaxp.SAXParserFactoryImpl");
    }
}

(2)具體工廠類:SAXParserFactoryImpl

SAXParserFactoryImpl 是 SAXParserFactory 的具體實現(xiàn),負(fù)責(zé)創(chuàng)建 SAXParser。

package org.apache.xerces.jaxp;

public class SAXParserFactoryImpl extends SAXParserFactory {
    
    @Override
    public SAXParser newSAXParser() throws ParserConfigurationException, SAXException {
        return new SAXParserImpl();
    }
}

(3)客戶端使用

客戶端通過 SAXParserFactory 來創(chuàng)建 SAXParser,解析 XML 文檔。

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class SAXParserExample {
    public static void main(String[] args) {
        try {
            // 獲取 SAXParserFactory 實例(抽象工廠)
            SAXParserFactory factory = SAXParserFactory.newInstance();
            
            // 使用工廠創(chuàng)建 SAXParser(具體產(chǎn)品)
            SAXParser parser = factory.newSAXParser();
            
            // 使用 SAXParser 解析 XML 文檔
            // 示例代碼忽略了具體 XML 文件的解析邏輯
            System.out.println("SAXParser created successfully!");
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3.這些應(yīng)用解決了什么問題?

解耦客戶端與具體實現(xiàn):  客戶端代碼不需要知道 DocumentBuilder 或 SAXParser 的具體實現(xiàn)類,只依賴于抽象工廠類和抽象產(chǎn)品類。這樣,XML 解析庫可以隨時切換實現(xiàn)(例如從 Apache Xerces 切換到其他實現(xiàn)),而無需修改客戶端代碼。

易于擴展:  當(dāng)需要增加新的 DocumentBuilder 或 SAXParser 實現(xiàn)時,只需增加新的工廠類,而不需要修改客戶端。通過使用抽象工廠模式,可以很容易地擴展和適應(yīng)新的需求。

集中控制對象創(chuàng)建:  使用工廠類來管理對象的創(chuàng)建,統(tǒng)一了對象的創(chuàng)建邏輯,避免了客戶端直接負(fù)責(zé)實例化的復(fù)雜性,使代碼更加靈活和可維護。

4.總結(jié)

在 JDK 中,諸如 DocumentBuilderFactory 和 SAXParserFactory 的類廣泛應(yīng)用了抽象工廠模式。這種模式確保了客戶端代碼與具體實現(xiàn)的解耦,并增強了系統(tǒng)的可擴展性和靈活性。通過使用抽象工廠模式,JDK 能夠在不同的 XML 解析器之間自由切換,而不影響客戶端代碼。

責(zé)任編輯:姜華 來源: 哪吒編程
相關(guān)推薦

2021-03-06 22:50:58

設(shè)計模式抽象

2020-10-19 09:28:00

抽象工廠模式

2021-09-29 13:53:17

抽象工廠模式

2011-11-17 16:03:05

Java工廠模式Clojure

2009-01-15 10:55:29

JavaScript設(shè)計模式抽象工廠

2020-12-17 09:38:16

設(shè)計模式參數(shù)

2011-07-28 09:50:58

設(shè)計模式

2009-07-09 17:30:59

Singleton模式C++ SingletJava Single

2020-08-21 07:23:50

工廠模式設(shè)計

2022-01-12 13:33:25

工廠模式設(shè)計

2015-11-03 09:43:43

avascript設(shè)計模式工廠模式

2011-07-21 14:33:02

設(shè)計模式

2023-08-07 06:30:15

抽象工廠模式軟件設(shè)計模式

2024-07-31 08:12:33

2010-04-19 09:30:00

工廠模式PHP設(shè)計模式

2024-03-06 13:19:19

工廠模式Python函數(shù)

2013-11-26 16:29:22

Android設(shè)計模式

2010-10-09 09:25:35

Python工廠模式

2022-05-09 08:04:50

工廠模式設(shè)計模式

2023-08-04 07:26:55

工廠類集中化設(shè)計模式
點贊
收藏

51CTO技術(shù)棧公眾號