小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

設(shè)計(jì)模式(1) 工廠方法模式

 行者花雕 2021-07-16
  • 創(chuàng)建型模式
  • 簡單工廠模式
  • 工廠方法模式
    • IOC與工廠方法模式的結(jié)合
    • 泛型工廠
    • 委托工廠

創(chuàng)建型模式

創(chuàng)建型模式可以隔離客戶程序?qū)π枰獙?shí)例化類型的依賴關(guān)系,這類模式一般通過將實(shí)例化具體對象的職責(zé)委托給第三方對象的方式,使得客戶程序或者外部系統(tǒng)在獲得所需的具體類型實(shí)例的同時(shí),而不必對其發(fā)生直接的引用。

創(chuàng)建型模式包括:

  • 工廠方法模式
  • 單例模式
  • 抽象工廠模式
  • 創(chuàng)建者模式
  • 原型模式

按照大多數(shù)設(shè)計(jì)模式書籍采用的順序,首先從工廠方法模式開始。

簡單工廠模式

簡單工廠模式并沒有被歸入23種設(shè)計(jì)模式之列,但可以作為學(xué)習(xí)工廠方法模式前的預(yù)備。簡單工廠模式在管理對象創(chuàng)建方面,提供的是最簡單的方案,它僅僅簡單的對不同類對象的創(chuàng)建進(jìn)行了一層薄薄的封裝,客戶程序在使用時(shí),通過向簡單工廠傳遞一個(gè)類型來指定要?jiǎng)?chuàng)建的對象,其UML類圖如下:
markdown

Client需要的是具體的產(chǎn)品ConcreteProductA或者ConcreteProductB,如果直接new()就會依賴對象實(shí)例,引入簡單工廠后,Client變成了依賴IProduct和SampleFactory。

代碼示例:

//產(chǎn)品接口
public interface IProduct { };
//具體產(chǎn)品
public class ConcreteProductA : IProduct { }
public class ConcreteProductB : IProduct { }

public enum Category { A, B }
//簡單工廠
public class SampleFactory
{
    public IProduct Create(Category category)
    {
        switch (category)
        {
            case Category.A:
                return new ConcreteProductA();
            case Category.B:
                return new ConcreteProductB();
            default:
                throw new ArgumentOutOfRangeException();
        }
    }

}

調(diào)用:

[Test]
public void SampleFactoryTest()
{
    SampleFactory sampleFactory = new SampleFactory();
    IProduct product = sampleFactory.Create(Category.A);
    Assert.AreEqual(product.GetType(), typeof(ConcreteProductA));
}

工廠方法模式

簡單工廠模式中的工廠負(fù)責(zé)生產(chǎn)所有的產(chǎn)品類型,但如果工廠負(fù)責(zé)生產(chǎn)的產(chǎn)品只有一種,就可以進(jìn)一步抽象了,這便出現(xiàn)了工廠模式。
GOF對工廠方法模式的描述是:
Define an interface for creating an object, but let subclasses decide which class toinstantiate. Factory Method lets a class defer instantiation to subclasses..
— Design Patterns : Elements of Reusable Object-Oriented Software

工廠方法模式定義了一個(gè)抽象的工廠,它的子類實(shí)體工廠都有統(tǒng)一通用的工廠方法,用來生產(chǎn)具體的產(chǎn)品,這樣就把類的實(shí)例化延遲到其子類。
工廠方法主要有四個(gè)角色:

  • 抽象產(chǎn)品類型(Product),工廠要加工的對象所具有的抽象特征實(shí)體。
  • 具體產(chǎn)品類型(Concrete Product),實(shí)現(xiàn)客戶程序所需要的抽象特質(zhì)的類型,它就是工廠需要延遲實(shí)例的備選對象。
  • 抽象工廠類型(IFactory),定義一個(gè)工廠方法的默認(rèn)實(shí)現(xiàn),它返回抽象產(chǎn)品類型。
  • 具體工廠類型(Concrete Factory):重新定義了產(chǎn)品創(chuàng)建過程,返回具體產(chǎn)品類型。

UML類圖
markdown

代碼示例:

//抽象產(chǎn)品類型
public interface IProduct
{
    string Name { get; } //抽象產(chǎn)品所必須具有的特征
}

//具體產(chǎn)品類型
public class ProductA : IProduct
{
    public string Name { get { return "A"; } }
}
public class ProductB : IProduct
{
    public string Name { get { return "B"; } }
}

//抽象工廠類型
public interface IFactory
{
    IProduct Create(); //抽象的工廠描述
}

//具體工廠類型
public class FactoryA : IFactory
{
    public IProduct Create()
    {
        return new ProductA();
    }
}

public class FactoryB : IFactory
{
    public IProduct Create()
    {
        return new ProductB();
    }
}

調(diào)用:

public class Client1
{
    public void SomeMethod()
    {
        IFactory factory = new FactoryA();
        IProduct product = factory.Create();
    }
}

客戶程序需要使用IProduct的時(shí)候,只需要獲取到IFactory,通過調(diào)用其統(tǒng)一制定的Create()方法就可以獲取到具體的產(chǎn)品,具體需要哪個(gè)產(chǎn)品由Factory決定。這樣就隔離了客戶程序?qū)唧w產(chǎn)品的依賴,但這里還有個(gè)問題是在獲取IFactory的時(shí)候需要初始化具體的工廠,這樣就對具體的工廠產(chǎn)生了依賴。

IOC與工廠方法模式的結(jié)合

為了解決上述問題,可以把IFactory作為客戶程序的參數(shù),然后采用依賴注入的方式將具體的工廠注入:

public class Client2
{
    private IFactory factory;
    public Client2(IFactory factory)
    {
        this.factory = factory;
    }
    public string SomeMethod()
    {
        IProduct product = factory.Create();
        return product.Name;
    }
}

這樣客戶程序就變成了真正地只依賴IFactory和IProduct了,但問題是不論采用哪種依賴注入框架,都需要注冊接口與實(shí)例的映射關(guān)系,那么這種方式就只是相當(dāng)于把對具體產(chǎn)品的依賴“甩”到了“客戶程序的客戶程序”,怎么辦呢,退無可退的時(shí)候,考慮把接口與實(shí)例的映射關(guān)系放到配置文件吧。

泛型工廠

上面的工廠方法模式中,每個(gè)具體的工廠負(fù)責(zé)生產(chǎn)一種產(chǎn)品,且都實(shí)現(xiàn)了抽象工廠的Create()方法,于是借助泛型可以實(shí)現(xiàn)進(jìn)一步的抽象:

public interface IFactory<T>
{
    T Create(); //抽象的工廠描述
}

public abstract class FactoryBase<T> : IFactory<T> where T : new()
{
    public virtual T Create()
    {
        return new T();
    }
}

public class ProductAFactory : FactoryBase<ProductA> {

    public override ProductA Create(){
        return new ProductA();
    }
}

public class ProductBFactory : FactoryBase<ProductB> { }

在抽象工廠和具體的工廠之間增加了支持泛型的FactoryBase,在這里實(shí)現(xiàn)了通用的Create()方法。如果某個(gè)具體工廠需要特殊的Create流程,只需重寫虛方法即可。這樣在工廠種類比較多而流程有大多相同的情況下,可以減少很多代碼。

委托工廠

前面代碼中的工廠生產(chǎn)的產(chǎn)品都是對象,如果需要生產(chǎn)的是方法呢,C#的委托機(jī)制可以方便地滿足這種需求。
委托的本質(zhì)是方法的指針,是對一類方法的抽象。所以委托本身就可以作為抽象產(chǎn)品的定義,而與委托簽名一致的方法就是具體產(chǎn)品了。

代碼示例:

public delegate int CalculateHandler(params int[] items);

public class Calculator
{
    public int Add(params int[] items)
    {
        int result = 0;
        foreach (var item in items)
        {
            result += item;
        }
        return result;
    }

    public int Multi(params int[] items)
    {
        int result = 1;
        foreach (var item in items)
        {
            result *= item;
        }
        return result;
    }
}

public class AddHandlerFactory : IFactory<CalculateHandler>
{
    public CalculateHandler Create()
    {
        return new Calculator().Add;
    }
}

public class MultiHandlerFactory : IFactory<CalculateHandler>
{
    public CalculateHandler Create()
    {
        return new Calculator().Multi;
    }
}

調(diào)用:

[Test]
public void CalculateHandlerTest()
{
    CalculateHandler addHandler = new AddHandlerFactory().Create();
    Assert.AreEqual(1 + 2 + 3, addHandler(1, 2, 3));

    CalculateHandler multiHandler = new MultiHandlerFactory().Create();
    Assert.AreEqual(1 * 2 * 3, multiHandler(1, 2, 3));
}

參考書籍:
王翔著 《設(shè)計(jì)模式——基于C#的工程化實(shí)現(xiàn)及擴(kuò)展》

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多