大牧絮叨設計模式:工廠方法模式

1、 工廠方法模式概述

工廠方法模式是一種創建模式,又被稱爲虛擬構造子模式(Virtual Constructor)或者多態性工廠模式(Polymoriphoic Factory)。工廠方法模式是目標是定義一個創建產品對象的工廠接口,將實際創建工作推遲到子類中。

1.1、 工廠方法模式核心組件

工廠方法模式是在簡單工廠模式上的改進,主要包含如下幾個角色及組件

  • 抽象工廠(Creator):整個工廠模式的核心角色,它與應用無關,主要在創建模式中規範和產品對應的工廠對象的標準化定義。
  • 具體工廠(Concrete Creator):實現了抽象工廠的具體工廠類,該類型是和應用直接交互的具體實現類,在應用程序中調用,用於創建產品對象。
  • 抽象產品(Product):工廠方法模式創建的所有類型的超級父類,該類型和具體業務有關,用於規範工廠方法模式中創建的方法對象具備的公共特徵行爲。
  • 具體產品(Concrete Product):該類型實現了抽象產品 父類,是工廠方法模式中具體創建的實例對象。

在這裏插入圖片描述

1.2、 工廠方法模式優缺點

優點:

在簡單工廠模式上的改進,核心工廠類不再負責所有產品的構建,而是將具體的工作交給子類進行實現,不再接觸和業務相關的具體細節,如此進一步抽象的結果,最直接的作用就是在滿足OCP原則的基礎上實現了功能的擴展。

缺點:

軟件的水平功能擴展已經非常可觀,但是對於新功能擴展,靈活性上稍有欠缺,在橫向擴展時如果出現新的業務邏輯就需要更改原有的工廠類型代碼予以滿足了。

在本章節的代碼演示中,爲了能用最簡潔的邏輯結構說明工廠方法模式,不進行多層構建,大家看代碼的時候可以自行拓展。

2、 Java實現

(1) 核心工廠聲明

package com.damu.inter;

/**
 * <p>項目文檔: 工廠接口</p>
 * @author 大牧
 * @version V1.0
 */
public interface IFactory<T> {
    /**
     * 獲取具體產品實例的方法
     * @return 返回創建的實例對象
     */
    T product();
}

(2) 核心產品聲明

package com.damu.inter;

/**
 * <p>項目文檔: 產品接口</p>
 *
 * @author 大牧
 * @version V1.0
 */
public interface IProduct {

    /**
     * 產品類型的公共方法
     * @return 返回產品信息
     */
    String getInformation();
}

(3) 產品具體實現

爲了簡潔起見,我們直接實現IProduct接口完成具體產品類的定義,不再進行多層聲明。

package com.damu.inter.product.impl;

import com.damu.inter.IProduct;

/**
 * <p>項目文檔: 產品具體實現</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class PhoneProduct implements IProduct {
    @Override
    public String getInformation() {
        return "電視很NB,報紙很NB,雜誌很NB,遊戲機很NB,小說很NB,最終都被手機幹掉了";
    }
}
package com.damu.inter.product.impl;

import com.damu.inter.IProduct;

/**
 * <p>項目文檔: TODO</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class ComputerProduct implements IProduct {
    @Override
    public String getInformation() {
        return "電腦,官方稱呼計算機,主要用於進行數據運算的一臺機器。";
    }
}

(4) 工廠具體實現

package com.damu.inter.factory.impl;

import com.damu.inter.IFactory;
import com.damu.inter.IProduct;
import com.damu.inter.product.impl.PhoneProduct;

/**
 * <p>項目文檔: 具體工廠</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class PhoneFactory implements IFactory<IProduct> {
    @Override
    public PhoneProduct product() {
        // 工廠標準方法中,完成指定產品對象的構建
        return new PhoneProduct();
    }
}
package com.damu.inter.factory.impl;

import com.damu.inter.IFactory;
import com.damu.inter.IProduct;
import com.damu.inter.product.impl.ComputerProduct;

/**
 * <p>項目文檔: TODO</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class ComputerFactory implements IFactory<IProduct> {
    @Override
    public ComputerProduct product() {
        // 工廠方法標註方法:完成對象的創建並返回
        return new ComputerProduct();
    }
}

(5) 代碼測試

package com.damu;

import com.damu.inter.IFactory;
import com.damu.inter.IProduct;
import com.damu.inter.factory.impl.ComputerFactory;
import com.damu.inter.factory.impl.PhoneFactory;
import com.damu.inter.product.impl.ComputerProduct;
import com.damu.inter.product.impl.PhoneProduct;

/**
 * <p>項目文檔: TODO</p>
 *
 * @author 大牧
 * @version V1.0
 */
public class Main {

    public static void main(String[] args) {
        // 創建工廠對象
        IFactory<IProduct> phoneFactory = new PhoneFactory();
        // 通過工廠穿件具體對象
        IProduct phoneProduct = phoneFactory.product();
        System.out.println(phoneProduct.getInformation());

        // 創建工廠對象
        IFactory<IProduct> computerFactory = new ComputerFactory();
        // 通過工廠創建具體對象
        IProduct computerProduct = computerFactory.product();
        System.out.println(computerProduct.getInformation());

    }
}

在測試代碼中,我們可以觀察到在獲取到統一的工廠實例對象後,通過工廠實例創建的具體產品對象,是根據在構建的時候的具體工廠決定的,也就是具體工廠和具體產品之間的業務關係是比較緊密的,運行結果如下:

/Library/../classes com.damu.Main
電視很NB,報紙很NB,雜誌很NB,遊戲機很NB,小說很NB,最終都被手機幹掉了
電腦,官方稱呼計算機,主要用於進行數據運算的一臺機器。

3、 Python實現

還原Java工廠方法模式的實現

"""
工廠方法模式
"""
import abc


class IFactory(metaclass=abc.ABCMeta):
    """工廠接口"""

    @abc.abstractmethod
    def product(self):
        raise NotImplementedError("該方法必須在工廠子類中實現")


class IProduct(metaclass=abc.ABCMeta):
    """產品接口"""

    @abc.abstractmethod
    def get_information(self):
        raise NotImplementedError("該方法必須在產品子類中實現")


class PhoneProduct(IProduct):
    """手機產品"""

    def get_information(self):
        return "電視很NB,報紙很NB,雜誌很NB,遊戲機很NB,小說很NB,最終都被手機幹掉了"


class ComputerProduct(IProduct):
    """電腦產品"""

    def get_information(self):
        return "電腦,官方稱呼計算機,主要用於進行數據運算的一臺機器"


class PhoneFactory(IFactory):
    """手機工廠"""

    def product(self):
        """生產手機對象的工廠方法"""
        return PhoneProduct()


class ComputerFactory(IFactory):
    """電腦工廠"""

    def product(self):
        """生產電腦對象的工廠方法"""
        return ComputerProduct()


if __name__ == "__main__":
    """測試代碼"""
    # 創建工廠實例
    phoneFactory = PhoneFactory()
    # 創建產品
    phone = phoneFactory.product()
    print(phone.get_information())

    # 創建電腦工廠
    computerFactory = ComputerFactory()
    # 創建產品
    computer = computerFactory.product()
    print(computer.get_information())

4、 Go實現

4.1、 定義工廠及產品接口

package main

import "fmt"

/*
定義產品接口
*/
type IProduct interface {
	// 獲取產品信息的方法
	GetInformation() string
}

/*
定義工廠接口
 */
type IFactory interface {
	// 生產產品的方法
	product() IProduct
}

4.2、 構建具體產品類型

/*
定義具體產品:手機、電腦
 */
type PhoneProduct struct {}
// 實現工廠方法
func (phone PhoneProduct) GetInformation() string {
	return "電視很NB,報紙很NB,雜誌很NB,遊戲機很NB,小說很NB,最終都被手機幹掉了"
}

/*
產品:電腦
 */
type ComputerProduct struct{}
// 實現工廠方法
func (computer ComputerProduct) GetInformation() string {
	return "電腦,官方稱呼計算機,主要用於進行數據運算的一臺機器。"
}

4.3、 構建具體工廠類型

/*
具體工廠:手機工廠
 */
type PhoneFactory struct{}
// 實現接口方法
func (phoneFactory PhoneFactory) product() IProduct  {
	return new(PhoneProduct)
}

/*
具體工廠:電腦工廠
 */
type ComputerFactory struct{}
// 實現接口方法
func (computerFactory ComputerFactory) product() IProduct  {
	return new(ComputerProduct)
}

4.4、測試代碼

func main()  {
	// 創建工廠對象
	phoneFactory := new(PhoneFactory)
	// 創建具體對象
	phone := phoneFactory.product()
	fmt.Println(phone.GetInformation())

	// 創建工廠對象
	computerFactory := new(ComputerFactory)
	// 創建具體對象
	computer := computerFactory.product()
	fmt.Println(computer.GetInformation())
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章