C# 設計模式(1)——簡單工廠模式、工廠模式、抽象工廠模式

魏楊楊發表於2021-12-08

1、前言

上一篇寫了設計模式原則有助於我們開發程式的時候能寫出高質量的程式碼(牽一髮而不動全身),這個系列還是做個筆記溫習一下各種設計模式,下面就看看簡單工廠模式、工廠模式、抽象工廠模式。

2、簡單工廠模式

其實我們可以這麼理解簡單工廠模式,就是專門負責生產物件的一個類,作用就是建立具體產品的例項。我們平時建立建立一個物件的時候通常都是new出來的,此時這個類就依賴與這個物件,說白了就是耦合度過高啦。需求變化的時候我們不得不去修改此類的原始碼。這時候就要用物件導向(OO)的思想去處理這個問題。把變化大的類封裝起來,實現就不去動它。下面看個栗子,就生產、製造不同的汽車分析簡單工廠模式的作用。

/// <summary>
/// 車  抽象類
/// </summary>
public abstract class Car
{
    /// <summary>
    /// 製造車--抽象方法
    /// </summary>
    public abstract void Make();
    /// <summary>
    /// 賣車--抽象方法
    /// </summary>
    public abstract void Sale();
}

/// <summary>
/// 奧迪車
/// </summary>
public class ADCar : Car
{
    public override void Make()
    {
        Console.WriteLine("製造了一輛奧迪車");
    }

    public override void Sale()
    {
        Console.WriteLine("銷售了一輛奧迪車");
    }
}
/// <summary>
/// 賓士車
/// </summary>
public class BCCar : Car
{
    public override void Make()
    {
        Console.WriteLine("製造了一輛賓士車");
    }

    public override void Sale()
    {
        Console.WriteLine("銷售了一輛賓士車");
    }
}

看客戶端的呼叫

Car c = new ADCar();
c.Make();
c.Sale();
Console.WriteLine("\n");
Car b = new BCCar();
b.Make();
b.Sale();

 我們可以看都是通過new一個ADCar 來建立一個例項, 想要賓士的一樣的要new一個出來 我想要n個那不是炸鍋了。所以這裡就建立一個車的簡單工廠類。讓這個工廠類來建立Car例項。這裡的switch是C#的語法糖,感覺是不是有點香。

/// <summary>
/// 車的工廠類
/// </summary>
public  class CarFactory
{
    public static Car OpCar(string carName)
    {
        Car? car = null;
        var ret = carName switch
        {
            "AD" => car=new ADCar(),
            "BC" => car=new BCCar(),
            _ => car=new ADCar()
        };
        return ret;
    }

}

//客戶端呼叫
Car cc = CarFactory.OpCar("AD");
cc.Make();
cc.Sale();

Car cc1 = CarFactory.OpCar("BC");
cc1.Make();
cc1.Sale();

 這時候是不是就可以了,解決了客戶端太過於依賴具體物件的問題,別急如果我再來一個寶馬 就要還新增一個繼承Car的BMCar 還要在 CarFactory的OpCar裡面再加一個判斷。按照開閉原則來說新增類沒有啥影響,但是修改了CarFactory裡面OpCar的程式碼就不符合開閉原則了。下面的工廠模式就專門解決這個問題。

3、工廠模式

在簡單工廠模式中系統難以擴充套件且違背了開閉原則,這樣使得簡單工廠的實現邏輯過於複雜。工廠模式就是把具體建立類的例項中放在子工廠類中,工廠類不再負責所有產品的建立工廠類只提供建立例項。還是看上面的栗子我們加一個抽象工廠類出來,讓不同的品牌去繼承

/// <summary>
/// 車工廠類
/// </summary>
public abstract class CarFactory1
{
    /// <summary>
    /// 抽象方法
    /// </summary>
    public abstract Car OpCar();
}
/// <summary>
/// 奧迪工廠
/// </summary>
public class ADCarFactory1 : CarFactory1
{
    public override Car OpCar()
    {
        return new ADCar();//在具體的工廠中例項化產品
    }
}
/// <summary>
/// 賓士工廠
/// </summary>
public class BCCarFactory1 : CarFactory1
{
    public override Car OpCar()
    {
        return new BCCar();//在具體的工廠中例項化產品
    }
}


//客戶端呼叫
CarFactory1 cf = new ADCarFactory1();
Car car = cf.OpCar();
car.Make();
car.Sale();

CarFactory1 cf2 = new BCCarFactory1();
Car car2 = cf2.OpCar();
car2.Make();
car2.Sale();

效果跟上面一樣的,這裡是不是就實現了新增一個寶馬的話不用修改Factory裡面的程式碼了只要在建立一個BMCarFactory1跟BMCar就可以了。我們要獲取一個產品的時候我們就獲取一個具體的工廠來例項它。 它是不是解決了簡單工廠的不足也符合了開閉原則。問題也來了如果我不單單要銷售車、賣車 搞大了我還要賣飛機賣火箭咋搞。這種不可能再去建立無數個工廠嘛。來看看抽象工廠模式。

4、抽象工廠模式

工廠模式它功能單一點只針對一個品牌,解決不了一系列的問題,賣火箭、賣飛機等等這些不同的品牌。如果我們在設計程式中顯然工廠模式已經滿足不了我們的需求了。抽象工廠模式就能很好的解決這個問題。這裡我們還是新增一個抽象類,他提供製造、銷售汽車的同事也提供製造銷售飛機。實現方法只要實現自己品牌的的產品就可以了。

/// <summary>
/// 產品抽象類
/// </summary>
public abstract class PcFactory
{
    /// <summary>
    ////// </summary>
    /// <returns></returns>
    public abstract Car OpCar();
    /// <summary>
    /// 飛機
    /// </summary>
    /// <returns></returns>
    public abstract Plan OpPlan();
}
/// <summary>
/// 奧迪pc工廠
/// </summary>
public class ADPcFactory : PcFactory
{
    public override Car OpCar()
    {
        return new ADCar();
    }

    public override Plan OpPlan()
    {
        return new ADPlan();
    }
}
/// <summary>
/// 賓士pc工廠
/// </summary>
public class BCPcFactory : PcFactory
{
    public override Car OpCar()
    {
        return new BCCar();
    }

    public override Plan OpPlan()
    {
        return new BCPlan();
    }
}

//客戶端呼叫
PcFactory pf = new ADPcFactory();
Car adc = pf.OpCar();
Plan adc2 = pf.OpPlan();
adc.Make();
adc.Sale();

adc2.Make();
adc2.Sale();

PcFactory pf2 = new BCPcFactory();
Car abc = pf2.OpCar();
Plan abc2 = pf2.OpPlan();
abc.Make();
abc.Sale();

abc2.Make();
abc2.Sale();

 我們可以看出抽象工廠跟工廠的區別就在於它能生產多種產品(車、飛機)工廠只能是單一的產品(車)。抽象類只注重建立的多個產品,不會關心具體的實現是什麼。實現又是不通的產品工廠實現的。這樣的話客戶端也從具體的產品中解耦出來。

5、總結

簡單工廠模式

優點:降低刻度段與具體產品的耦合度,實現new讓工廠類去完成,也提高了程式碼的複用率。

缺點:違反了開閉原則系統擴充套件困難,而且工廠類集中了所有的業務邏輯一旦出問題整個系統都要受牽連。

工廠模式

優點:符合開閉原則新增功能不會區修改以前的程式碼。

缺點:產品功能單一寫車的功能只能弄車,而不能加飛機、火箭的操作。

抽象工廠模式

優點:降低系統耦合度利於維護擴充套件,對於加系列產品符合開閉原則;

缺點:對於功能新增又不符合開閉原則了。看著是不是跟優點有衝突。這樣說吧我現在要加一個寶馬類不用修改業務邏輯新增一個BMCarFactory1跟BMCar就可以了。這是系列問題。如果我要加一個銷燬的方法(之前就定義了製作、銷售)那是不是還要在抽象類Car、Plan裡面加一個抽象方法 繼承裡面的通通都要實現它。所以程式設計之初沒有考慮到後面一個一個的改很麻煩。

一個系統要求不被所有客戶端依賴到具體的實現這是所有工廠模式的應用的前提,這就要具體問題具體分析了。不可能說我要列印一個Holl Word還來搞設計模式嘛,高射炮打蚊子沒有必要。各種模式都有好有壞,相對論就是這麼說的,你得到一些的時候必然會失去一些,快樂要有悲傷作伴,雨過自然天晴嗎。加了設計模式以後程式碼量肯定要上去的帶給我們方便的同時也會增加風險。以前不解為啥要建立那麼多專案,資料夾,現在想想就那麼回事了。

PS:流年似水,歲月如歌,承受委屈是一種胸懷,接受誤解是一種心懷,這個世界上失去什麼東西都不可怕,惟一可怕的是失去你的心,失去你的勇氣,只要你堅韌不拔地奮鬥,只要你眼睛看向未來,生命就永遠屬於你,生命的輝煌也一定永遠屬於你。

相關文章