天天看點

【愚公系列】2021年12月 二十三種設計模式(零)-簡單工廠模式(Simple Factory Pattern)

文章目錄

前言

一、簡單工廠模式(Simple Factory Pattern)

二、使用步驟

角色

示例

總結

優點

缺點

使用場景

設計模式(Design pattern)是一套被反複使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人了解、保證代碼可靠性。 毫無疑問,設計模式于己于他人于系統都是多赢的,設計模式使代碼編制真正工程化,設計模式是軟體工程的基石,如同大廈的一塊塊磚石一樣。項目中合理的運用設計模式可以完美的解決很多問題,每種模式在現在中都有相應的原理來與之對應,每一個模式描述了一個在我們周圍不斷重複發生的問題,以及該問題的核心解決方案,這也是它能被廣泛應用的原因。

提示:以下是本篇文章正文内容,下面案例可供參考

簡單工廠模式屬于建立型模式,又叫做靜态工廠方法(Static Factory Method)模式,但不屬于23種GoF設計模式之一。學習簡單工廠模式是學習其它工廠模式的前提條件。

簡單工廠模式是由一個工廠對象決定建立出哪一種産品類的執行個體。簡單工廠模式是工廠模式家族中最簡單實用的模式,可以了解為是不同工廠模式的一個特殊實作。

1、工廠(Creator)

簡單工廠模式的核心,它負責實作建立所有執行個體的内部邏輯。工廠類的建立産品類的方法可以被外界直接調用,建立所需的産品對象;

2、抽象産品(Product)

簡單工廠模式所建立的所有對象的抽象基類,它負責描述所有執行個體所共有的公共接口;

3、具體産品(Concrete Product)

這是簡單工廠模式的建立目标,所有建立的對象都是充當這個角色的某個具體類的執行個體。

【愚公系列】2021年12月 二十三種設計模式(零)-簡單工廠模式(Simple Factory Pattern)
命名空間SimpleFactory中包含抽象水果基類Fruit、三個具體水果類、水果工廠類FruitFactory、未知水果異常類UnknowFruitException。本案例将向大家展示如何使用簡單工廠模式來生産不同種類的水果。

public abstract class Fruit {
 
    protected Color Color { get; set; } = Color.Orange;
 
    protected abstract string BornInfo();
 
    protected const string LINE_BREAK =
        "------------------------------------------------------------";
 
    public void WhatsFruit() {
        Console.WriteLine("Printing!");
        OnPrint();
        Console.WriteLine("Printed!");
        OnPrinted();
    }
 
    protected virtual void OnPrint() {
        Console.WriteLine($"I'm a(n) {this.ToString().Replace(nameof(SimpleFactory) + ".", "")} " +
                            $"with {Color.ToString()} and I born in {BornInfo()}!");
    }
 
    protected virtual void OnPrinted() {
        Console.WriteLine(LINE_BREAK);
    }
 
}      

抽象水果基類Fruit 包含顔色Color屬性、出生資訊BornInfo抽象方法、這是什麼水果WhatsFruit方法、列印水果OnPrint和列印完OnPrinted方法。

public class Apple : Fruit {

    public Apple() {
        Color = Color.Red;
    }

    protected override string BornInfo() => "summer";

    protected override void OnPrint() {
        Console.WriteLine($"I'm an apple with {Color.ToString()},not an IPhone!");
    } 

}      
public class Orange : Fruit {

    protected override string BornInfo() => "autumn";

    protected override void OnPrinted() {
        Console.WriteLine("override OnPrinted()!");
        Console.WriteLine(LINE_BREAK);
    }

}      
public class Pear : Fruit {

    public Pear() {
        Color = Color.Yellow;
    }

    protected override string BornInfo() => "China";

}      

具體水果類,蘋果Apple類、橘子Orange類和梨子Pear類,各自實作或重寫不同的構造函數、抽象方法、虛拟方法和屬性。

public enum FruitType {
    Unknow = -1,
    Apple,
    Orange,
    Pear
}      
public static class FruitFactory {

    public static Fruit CreateFruit(FruitType type) {
        Fruit fruit = null;
        switch (type) {
            case FruitType.Apple:
                fruit = new Apple();
                break;
            case FruitType.Orange:
                fruit = new Orange();
                break;
            case FruitType.Pear:
                fruit = new Pear();
                break;
            default:
                throw new UnknowFruitException();
        }

        return fruit;
    }

}      

水果工廠類FruitFactory,該類是簡單工廠的核心類,包含CreateFruit方法,傳遞FruitType參數以便确定産出何種水果。方法傳回抽象水果基類,以便調用方使用基類變量接受傳回值。

public class UnknowFruitException : Exception {

    public UnknowFruitException()
        : base("Not Supported Fruit!") {

    }

    public UnknowFruitException(string message, Exception innerException)
        : base(message, innerException) {

    }

}      

使用未知水果異常類UnknowFruitException,進行簡單的異常處理。

public static void Main(string[] args) {
    try {
        var fruit = FruitFactory.CreateFruit(FruitType.Pear);
        fruit.WhatsFruit();

        fruit = FruitFactory.CreateFruit(FruitType.Apple);
        fruit.WhatsFruit();

        fruit = FruitFactory.CreateFruit(FruitType.Orange);
        fruit.WhatsFruit();

        fruit = FruitFactory.CreateFruit(FruitType.Unknow);
        fruit.WhatsFruit();
    }
    catch (UnknowFruitException ex) {
        Console.WriteLine(nameof(UnknowFruitException) + ":" + ex.Message);
    }
    catch (Exception ex) {
        Console.WriteLine(nameof(Exception) + ":" + ex.Message);
    }

    Console.ReadKey();
}      

調用方用變量fruit接受水果工廠不同的産出,由WhatsFruit方法在控制台列印出水果資訊,用catch分别處理不同類型的異常。以下是這個案例的輸出結果:

Printing!
I'm a(n) Pear with Color [Yellow] and I born in China!
Printed!
-----------------------------------------------------------
Printing!
I'm an apple with Color [Red],not an IPhone!
Printed!
-----------------------------------------------------------
Printing!
I'm a(n) Orange with Color [Orange] and I born in autumn!
Printed!
override OnPrinted()!
-----------------------------------------------------------
UnknowFruitException:Not Supported Fruit!      

1、工廠類是整個模式最核心的部分,包含了對象的建立邏輯。調用者無需關心對象建立的細節,隻要給出參數,就可以得到相應的對象;

2、他們之間互相獨立,各司其職,有利于整個軟體體系架構。

1、由于工廠類集中了所有執行個體的建立邏輯,違反了高内聚責任配置設定原則;

2、将全部建立邏輯集中到了一個工廠類中,如果需要添加新的類,則就需要改變工廠類了,明顯違反開閉原則。工廠方法模式中這個問題有一定程度的緩解。

1、工廠類負責建立的對象比較少;

2、客戶隻知道傳入工廠類的參數,對于建立對象的細節不關心或無法知道;

3、由于簡單工廠很容易違反高内聚責任配置設定原則,是以在實際開發中很少用到。

繼續閱讀