C#設計模式系列:抽象工廠模式(AbstractFactory)


1. 抽象工廠模式簡介

1.1 定義

  抽象工廠(Abstract Factory)模式意圖:為創建一組相關或相互依賴對象提供了一個接口,而且無需指定它們的具體類。

  抽象工廠可以向客戶提供一個接口,是客戶可以在不必指定產品具體類型的情況下,創建多個產品家族中的產品對象,它強調的“系列對象”的變化。

1.2 使用頻率

  

2. 抽象工廠模式結構

2.1 結構圖

2.2 參與者

  抽象工廠模式參與者:

  ◊ AbstractFactory:聲明一個創建抽象產品對象的操作接口

  ◊ ConcreteFactory:實現創建具體產品對象的操作

  ◊ AbstractProduct:聲明一類產品對象接口

  ◊ Product

    °定義一個被相應具體工廠創建的產品對象

    °實現AbstractProduct接口

  ◊ Client:使用AbstractFactory和AbstractProduct類聲明的接口

  在抽象工廠模式中,產品的創建由ConcreteFactory來完成,從結構圖中可以看出,抽象工廠模式的ConcreteFactory不是負責一種具體Product的創建,而是負責一個Product族的創建。

3. 抽象工廠模式結構實現

  AbstractProductA.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Structural
{
    public abstract class AbstractProductA
    {
    }
}

  AbstractProductB.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Structural
{
    public abstract class AbstractProductB
    {
        public abstract void Interact(AbstractProductA a);
    }
}

  ProductA1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Structural
{
    public class ProductA1 : AbstractProductA
    {
    }
}

  ProductB1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Structural
{
    public class ProductB1 : AbstractProductB
    {
        public override void Interact(AbstractProductA a)
        {
            Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name);
        }
    }
}

  ProductA2.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Structural
{
    public class ProductA2 : AbstractProductA
    {
    }
}

  ProductB2.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Structural
{
    public class ProductB2 : AbstractProductB
    {
        public override void Interact(AbstractProductA a)
        {
            Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name);
        }
    }
}

  ConcreteFactory1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Structural
{
   public class ConcreteFactory1 : AbstractFactory
    {
        public override AbstractProductA CreateProductA()
        {
            return new ProductA1();
        }

        public override AbstractProductB CreateProductB()
        {
            return new ProductB1();
        }
    }
}

  ConcreteFactory2.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Structural
{
    public class ConcreteFactory2 : AbstractFactory
    {
        public override AbstractProductA CreateProductA()
        {
            return new ProductA2();
        }

        public override AbstractProductB CreateProductB()
        {
            return new ProductB2();
        }
    }
}

  AbstractFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Structural
{
    public abstract class AbstractFactory
    {
        public abstract AbstractProductA CreateProductA();

        public abstract AbstractProductB CreateProductB();
    }
}

  Client.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Structural
{
    public class Client
    {
        private AbstractProductA _abstractProductA;
        private AbstractProductB _abstractProductB;

        public Client(AbstractFactory factory)
        {
            _abstractProductB = factory.CreateProductB();
            _abstractProductA = factory.CreateProductA();
        }

        public void Run()
        {
            _abstractProductB.Interact(_abstractProductA);
        }
    }
}

  Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DesignPatterns.AbstractFactoryPattern.Structural;

namespace DesignPatterns.AbstractFactoryPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            // Abstract factory #1
            AbstractFactory factory1 = new ConcreteFactory1();
            Client client1 = new Client(factory1);
            client1.Run();
            
            // Abstract factory #2
            AbstractFactory factory2 = new ConcreteFactory2();
            Client client2 = new Client(factory2);
            client2.Run();

            // Wait for user input
            Console.ReadKey();
        }
    }
}

  運行輸出:

ProductB1 interacts with ProductA1
ProductB2 interacts with ProductA2
請按任意鍵繼續. . .

4. 抽象工廠模式實踐應用

  以KFC為例闡述抽象工廠模式的應用,假設現在KFC的食品直接沒有任何關聯,不可以分類,各個Product相互獨立。這樣工廠方法模式就可以很好解決,定義一系列的簡單工廠,用戶沒要求一種食品就使用一個合適的簡單工廠來生產相應的Product就可以。

  但實際情況下,KFC的產品還可以進行套餐出售,假設KFC的產品可以分為食品Food和飲料Drink,Food和Drink分別構成了一個產品族,一個產品族就是一系列相似對象的抽象。KFC出售2種套餐,一種是經濟型,包括雞翅和可樂;另一種是豪華型,包括雞腿和咖啡。用戶只需要指出需要的套餐名即可獲得相應的Food和Drink。這種情況下,工廠方法模式將不再適用,而采用抽象工廠模式進行實現。

  KFCFood.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Practical
{
    /// <summary>
    /// Product族1,KFC食品
    /// </summary>
    public abstract class KFCFood
    {
        public abstract void Display();
    }
}

  Chicken.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Practical
{
    public class Chicken : KFCFood
    {
        public override void Display()
        {
            Console.WriteLine("雞腿 + 1");
        }
    }
}

  Wings.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Practical
{
    public class Wings : KFCFood
    {
        public override void Display()
        {
            Console.WriteLine("雞翅 + 1");
        }
    }
}

  KFCDrink.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Practical
{
    /// <summary>
    /// Product族2,KFC飲料
    /// </summary>
    public abstract class KFCDrink
    {
        public abstract void Display();
    }
}

  Coke.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Practical
{
    public class Coke : KFCDrink
    {
        public override void Display()
        {
            Console.WriteLine("可樂 + 1");
        }
    }
}

  Coffee.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Practical
{
    public class Coffee : KFCDrink
    {
        public override void Display()
        {
            Console.WriteLine("咖啡 + 1");
        }
    }
}

  IKFCFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Practical
{
    /// <summary>
    /// 抽象工廠,生產套餐
    /// </summary>
    public interface IKFCFactory
    {
        KFCFood CreateFood();
        KFCDrink CreateDrink();
    }
}

  CheapPackageFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Practical
{
    /// <summary>
    /// 經濟型套餐,包括雞翅和可樂
    /// </summary>
    public class CheapPackageFactory : IKFCFactory
    {
        public KFCFood CreateFood()
        {
            return new Wings();
        }
        public KFCDrink CreateDrink()
        {
            return new Coke();
        }
    }
}

  LuxuryPackageFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactoryPattern.Practical
{
    /// <summary>
    /// 豪華型套餐,包括雞腿和咖啡
    /// </summary>
    public class LuxuryPackageFactory : IKFCFactory
    {
        public KFCFood CreateFood()
        {
            return new Chicken();
        }

        public KFCDrink CreateDrink()
        {
            return new Coffee();
        }
    }
}

  Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DesignPatterns.AbstractFactoryPattern.Practical;

namespace DesignPatterns.AbstractFactoryPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            IKFCFactory factory = new CheapPackageFactory();
            KFCFood food = factory.CreateFood();
            food.Display();

            KFCDrink drink = factory.CreateDrink();
            drink.Display();           
        }
    }
}

  運行輸出:

雞翅 + 1
可樂 + 1
請按任意鍵繼續. . .

5. 抽象工廠模式應用分析

5.1 抽象工廠模式適用情形

  ◊ 同一個產品族的Product在一起使用時,而且它們之間是相互依賴的,不可分離

  ◊ 系統需要由相互關聯的多個對象來構成

  ◊ 當想提供一組對象而不顯示它們的實現過程,只顯示它們的接口

  ◊ 系統不應當依賴一些具體Product類

5.2 抽象工廠模式的特點

  ◊ 隔離了具體類的生成,客戶不需要知道怎樣生成每一個具體Product,什么時間生成的。它將客戶與具體的類分離,依賴於抽象類,耦合性低。

  ◊ 一個產品族中的多個對象設計成一起工作,它能保證客戶端始終只使用一個產品族中的對象。這對一些需要根據當前環境來決定其行為的軟件系統來說是非常實用的一種設計模式。

  ◊ 有利於更換產品系列,由於客戶端只依賴於抽象類,更換產品系列時,只需要更改一下具體工廠名就可以。

  ◊ 難以支持新種類的產品,這是因為抽象工廠接口確定了可以被創建的產品集合,支持新種類的產品就需要擴展該工廠接口,這將引起抽象工廠類及其所有子類的改變。

5.3 抽象工廠模式與工廠方法模式區別

  ◊ 工廠方法模式只有一個抽象產品類,而抽象工廠模式可以有多個抽象產品類。

  ◊ 工廠方法模式針對一個產品等級結構,可以派生出多個具體產品類;抽象工廠模式針對面向多個產品等級結構,每個抽象產品類可以派生出多個具體產品類。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM