C#設計模式學習筆記:(3)抽象工廠模式

    本筆記摘抄自:http://www.javashuo.com/article/p-hjobwtrt-hy.html,記錄一下學習過程以備後續查用。html

    1、引言數據庫

    接上一篇C#設計模式學習筆記:簡單工廠模式(工廠方法模式前奏篇),經過簡單工廠模式的瞭解,它的缺點就是隨着需求的變化咱們要不停地修改工廠裏設計模式

    上一篇文章咱們講了工廠方法模式,它是爲了解決簡單工廠模式所面對的問題:若是咱們增長新的產品,工廠類的方法就要修改自己的代碼,增長產品越ide

多,其邏輯越複雜,同時這樣的修改也不符合開放閉合原則OCP--對增長代碼開放,對修改代碼關閉。爲了解決簡單工廠的問題,咱們引出了工廠方法模式,工具

經過子類化工廠類,解決了工廠類責任的劃分,使得產品和相應的工廠一一對應,符合了OCP。post

    若是咱們要設計一套房子,固然咱們知道房子是由房頂、地板、窗戶、房門等組成的,先設計一套古典風格的房子,再建立一套現代風格的房子,再建立學習

一套歐式風格的房子,這麼多套房子,咱們該怎麼辦呢?今天咱們要講的抽象工廠模式能夠很好地解決多套變化的問題。ui

    2、抽象工廠模式介紹atom

    抽象工廠模式:英文名稱--Abstract Factory Pattern;分類--建立型。url

    2.一、動機(Motivate)

    在軟件系統中,常常面臨着"一系列相互依賴的對象"的建立工做,同時,因爲需求的變化,每每存在更多系列對象的建立工做。如何應對這種變化?如何

繞過常規的對象建立方法(new),提供一種"封裝機制"來避免客戶程序和這種"多系列具體對象建立工做"的緊耦合?

    2.二、意圖(Intent)

    提供一個建立一系列相關或相互依賴對象的接口,而無需指定它們具體的類。——《設計模式》GoF

    2.三、結構圖(Structure)

    該圖是抽象工廠的UML圖,結合抽象工廠的意圖、動機和圖示來理解該模式,今天咱們就以建設房子爲例來講明抽象工廠的實現機理。

    2.四、模式的組成

    從上圖能夠看出,在抽象工廠模式的結構圖有如下角色:

    1)抽象產品類角色(AbstractProduct):爲抽象工廠中相互依賴的每種產品定義抽象接口對象,也能夠這樣說,有幾種產品,就要聲明幾個抽象角色,

每個抽象產品角色和一種具體的產品相匹配。

    2)具體產品類(ConcreteProduct):具體產品類實現了抽象產品類,是針對某個具體產品的實現的類型。

    3)抽象工廠類角色(AbstractFactory):定義了建立一組相互依賴的產品對象的接口操做,每種操做和每種產品一一對應。

    4)具體工廠類角色(ConcreteFactory):實現抽象類裏全部抽象接口操做,能夠建立某系列具體的產品,這些具體的產品是「抽象產品類角色」的子類。

    2.五、抽象工廠的具體代碼實現

    隨着咱們年齡的增加,咱們也到告終婚的年齡,結婚首要的問題就是房子的問題。假設我有一個頗有錢的爸爸(呃,發夢中……),個人哥哥們但願能有

一套歐式風格的房子,再加上田園風光,清閒自在。而我就不同了,我但願有一套現代樣式的房子。因爲房子由房頂、地板、窗戶和房門組成(其餘組

件暫時省略),每套房子的房頂、地板、窗戶和房門都是一個體系的。

    下面讓咱們看看如何使用抽象工廠模式來實現不一樣房屋的建造:

    class Program
    {
        /// <summary>
        /// 房頂抽象類,子類的房頂必須繼承該類。
        /// </summary>
        public abstract class Roof
        {
            /// <summary>
            /// 建立房頂
            /// </summary>
            public abstract void Create();
        }

        /// <summary>
        /// 地板抽象類,子類的地板必須繼承該類。
        /// </summary>
        public abstract class Floor
        {
            /// <summary>
            /// 建立地板
            /// </summary>
            public abstract void Create();
        }

        /// <summary>
        /// 窗戶抽象類,子類的窗戶必須繼承該類。
        /// </summary>
        public abstract class Window
        {
            /// <summary>
            /// 建立窗戶
            /// </summary>
            public abstract void Create();
        }

        /// <summary>
        /// 房門抽象類,子類的房門必須繼承該類。
        /// </summary>
        public abstract class Door
        {
            /// <summary>
            /// 建立房門
            /// </summary>
            public abstract void Create();
        }

        /// <summary>
        /// 歐式的房頂
        /// </summary>
        public class EuropeanRoof : Roof
        {
            public override void Create()
            {
                Console.WriteLine("建立歐式的房頂");
            }
        }

        /// <summary>
        /// 歐式的地板
        /// </summary>
        public class EuropeanFloor : Floor
        {
            public override void Create()
            {
                Console.WriteLine("建立歐式的地板");
            }
        }

        /// <summary>
        ///歐式的窗戶
        /// </summary>
        public class EuropeanWindow : Window
        {
            public override void Create()
            {
                Console.WriteLine("建立歐式的窗戶");
            }
        }

        /// <summary>
        /// 歐式的房門
        /// </summary>
        public class EuropeanDoor : Door
        {
            public override void Create()
            {
                Console.WriteLine("建立歐式的房門");
            }
        }

        /// <summary>
        /// 現代的房頂
        /// </summary>
        public class ModernizationRoof : Roof
        {
            public override void Create()
            {
                Console.WriteLine("建立現代的房頂");
            }
        }

        /// <summary>
        /// 現代的地板
        /// </summary>
        public class ModernizationFloor : Floor
        {
            public override void Create()
            {
                Console.WriteLine("建立現代的地板");
            }
        }

        /// <summary>
        /// 現代的窗戶
        /// </summary>
        public class ModernizationWindow : Window
        {
            public override void Create()
            {
                Console.WriteLine("建立現代的窗戶");
            }
        }

        /// <summary>
        /// 現代的房門
        /// </summary>
        public class ModernizationDoor : Door
        {
            public override void Create()
            {
                Console.WriteLine("建立現代的房門");
            }
        }

        /// <summary>
        /// 抽象工廠類,提供建立不一樣類型房子的接口。
        /// </summary>
        public abstract class AbstractFactory
        {
            //抽象工廠提供建立一系列產品的接口,此處給出了房頂、地板、窗戶和房門的建立接口。
            public abstract Roof CreateRoof();
            public abstract Floor CreateFloor();
            public abstract Window CreateWindow();
            public abstract Door CreateDoor();
        }

        /// <summary>
        /// 歐式風格房子的工廠,負責建立歐式風格的房子。
        /// </summary>
        public class EuropeanFactory : AbstractFactory
        {
            //製做歐式房頂
            public override Roof CreateRoof()
            {
                return new EuropeanRoof();
            }

            //製做歐式地板
            public override Floor CreateFloor()
            {
                return new EuropeanFloor();
            }

            //製做歐式窗戶
            public override Window CreateWindow()
            {
                return new EuropeanWindow();
            }

            //製做歐式房門
            public override Door CreateDoor()
            {
                return new EuropeanDoor();
            }
        }

        /// <summary>
        /// 如今風格房子的工廠,負責建立現代風格的房子。
        /// </summary>
        public class ModernizationFactory : AbstractFactory
        {
            //製做現代房頂
            public override Roof CreateRoof()
            {
                return new ModernizationRoof();
            }

            //製做現代地板
            public override Floor CreateFloor()
            {
                return new ModernizationFloor();
            }

            //製做現代窗戶
            public override Window CreateWindow()
            {
                return new ModernizationWindow();
            }

            //製做現代房門
            public override Door CreateDoor()
            {
                return new ModernizationDoor();
            }
        }

        static void Main(string[] args)
        {
            #region 抽象工廠模式
            //歐式風格的房子
            AbstractFactory europeanFactory = new EuropeanFactory();
            europeanFactory.CreateRoof().Create();
            europeanFactory.CreateFloor().Create();
            europeanFactory.CreateWindow().Create();
            europeanFactory.CreateDoor().Create();

            //現代風格的房子
            AbstractFactory modernizationFactory = new ModernizationFactory();
            modernizationFactory.CreateRoof().Create();
            modernizationFactory.CreateFloor().Create();
            modernizationFactory.CreateWindow().Create();
            modernizationFactory.CreateDoor().Create();

            Console.Read();
            #endregion
        }
    }
View Code

    運行結果以下:

    2.六、 抽象工廠應對需求變動

    假設個人姐姐一看咱們的房子很好,她但願有一套古典風格的房子,怎麼處理呢?

    class Program
    {
        /// <summary>
        /// 房頂抽象類,子類的房頂必須繼承該類。
        /// </summary>
        public abstract class Roof
        {
            /// <summary>
            /// 建立房頂
            /// </summary>
            public abstract void Create();
        }

        /// <summary>
        /// 地板抽象類,子類的地板必須繼承該類。
        /// </summary>
        public abstract class Floor
        {
            /// <summary>
            /// 建立地板
            /// </summary>
            public abstract void Create();
        }

        /// <summary>
        /// 窗戶抽象類,子類的窗戶必須繼承該類。
        /// </summary>
        public abstract class Window
        {
            /// <summary>
            /// 建立窗戶
            /// </summary>
            public abstract void Create();
        }

        /// <summary>
        /// 房門抽象類,子類的房門必須繼承該類。
        /// </summary>
        public abstract class Door
        {
            /// <summary>
            /// 建立房門
            /// </summary>
            public abstract void Create();
        }

        /// <summary>
        /// 歐式的房頂
        /// </summary>
        public class EuropeanRoof : Roof
        {
            public override void Create()
            {
                Console.WriteLine("建立歐式的房頂");
            }
        }

        /// <summary>
        /// 歐式的地板
        /// </summary>
        public class EuropeanFloor : Floor
        {
            public override void Create()
            {
                Console.WriteLine("建立歐式的地板");
            }
        }

        /// <summary>
        ///歐式的窗戶
        /// </summary>
        public class EuropeanWindow : Window
        {
            public override void Create()
            {
                Console.WriteLine("建立歐式的窗戶");
            }
        }

        /// <summary>
        /// 歐式的房門
        /// </summary>
        public class EuropeanDoor : Door
        {
            public override void Create()
            {
                Console.WriteLine("建立歐式的房門");
            }
        }

        /// <summary>
        /// 現代的房頂
        /// </summary>
        public class ModernizationRoof : Roof
        {
            public override void Create()
            {
                Console.WriteLine("建立現代的房頂");
            }
        }

        /// <summary>
        /// 現代的地板
        /// </summary>
        public class ModernizationFloor : Floor
        {
            public override void Create()
            {
                Console.WriteLine("建立現代的地板");
            }
        }

        /// <summary>
        /// 現代的窗戶
        /// </summary>
        public class ModernizationWindow : Window
        {
            public override void Create()
            {
                Console.WriteLine("建立現代的窗戶");
            }
        }

        /// <summary>
        /// 現代的房門
        /// </summary>
        public class ModernizationDoor : Door
        {
            public override void Create()
            {
                Console.WriteLine("建立現代的房門");
            }
        }

        /// <summary>
        ///古典的房頂
        /// </summary>
        public class ClassicalRoof : Roof
        {
            public override void Create()
            {
                Console.WriteLine("建立古典的房頂");
            }
        }

        /// <summary>
        /// 古典的地板
        /// </summary>
        public class ClassicalFloor : Floor
        {
            public override void Create()
            {
                Console.WriteLine("建立古典的地板");
            }
        }

        /// <summary>
        /// 古典的窗戶
        /// </summary>
        public class ClassicalWindow : Window
        {
            public override void Create()
            {
                Console.WriteLine("建立古典的窗戶");
            }
        }

        /// <summary>
        /// 古典的房門
        /// </summary>
        public class ClassicalDoor : Door
        {
            public override void Create()
            {
                Console.WriteLine("建立古典的房門");
            }
        }

        /// <summary>
        /// 抽象工廠類,提供建立不一樣類型房子的接口。
        /// </summary>
        public abstract class AbstractFactory
        {
            //抽象工廠提供建立一系列產品的接口,此處給出了房頂、地板、窗戶和房門的建立接口。
            public abstract Roof CreateRoof();
            public abstract Floor CreateFloor();
            public abstract Window CreateWindow();
            public abstract Door CreateDoor();
        }

        /// <summary>
        /// 歐式風格房子的工廠,負責建立歐式風格的房子。
        /// </summary>
        public class EuropeanFactory : AbstractFactory
        {
            //製做歐式房頂
            public override Roof CreateRoof()
            {
                return new EuropeanRoof();
            }

            //製做歐式地板
            public override Floor CreateFloor()
            {
                return new EuropeanFloor();
            }

            //製做歐式窗戶
            public override Window CreateWindow()
            {
                return new EuropeanWindow();
            }

            //製做歐式房門
            public override Door CreateDoor()
            {
                return new EuropeanDoor();
            }
        }

        /// <summary>
        /// 如今風格房子的工廠,負責建立現代風格的房子。
        /// </summary>
        public class ModernizationFactory : AbstractFactory
        {
            //製做現代房頂
            public override Roof CreateRoof()
            {
                return new ModernizationRoof();
            }

            //製做現代地板
            public override Floor CreateFloor()
            {
                return new ModernizationFloor();
            }

            //製做現代窗戶
            public override Window CreateWindow()
            {
                return new ModernizationWindow();
            }

            //製做現代房門
            public override Door CreateDoor()
            {
                return new ModernizationDoor();
            }
        }

        /// <summary>
        /// 古典風格房子的工廠,負責建立古典風格的房子。
        /// </summary>
        public class ClassicalFactory : AbstractFactory
        {
            //建立古典房頂
            public override Roof CreateRoof()
            {
                return new ClassicalRoof();
            }

            //建立古典地板
            public override Floor CreateFloor()
            {
                return new ClassicalFloor();
            }

            //建立古典窗戶
            public override Window CreateWindow()
            {
                return new ClassicalWindow();
            }

            //建立古典房門
            public override Door CreateDoor()
            {
                return new ClassicalDoor();
            }
        }

        static void Main(string[] args)
        {
            #region 抽象工廠模式
            //歐式風格的房子
            AbstractFactory europeanFactory = new EuropeanFactory();
            europeanFactory.CreateRoof().Create();
            europeanFactory.CreateFloor().Create();
            europeanFactory.CreateWindow().Create();
            europeanFactory.CreateDoor().Create();

            //現代風格的房子
            AbstractFactory modernizationFactory = new ModernizationFactory();
            modernizationFactory.CreateRoof().Create();
            modernizationFactory.CreateFloor().Create();
            modernizationFactory.CreateWindow().Create();
            modernizationFactory.CreateDoor().Create();

            //古典風格的房子
            AbstractFactory classicalFactory = new ClassicalFactory();
            classicalFactory.CreateRoof().Create();
            classicalFactory.CreateFloor().Create();
            classicalFactory.CreateWindow().Create();
            classicalFactory.CreateDoor().Create();

            Console.Read();
            #endregion
        }
    }
View Code

    運行結果以下:

    從上面代碼能夠看出,須要添加5個類:4個類分別建立古典風格的房頂、地板、窗戶和房門的具體產品,另一個是古典風格房子的工廠類,負責建立

古典風格的房子。

    從上面代碼能夠看出,抽象工廠對於系列產品的變化支持開閉原則(對擴展開放,對修改封閉),擴展起來很是簡便。可是,抽象工廠對於增長新產品

這種狀況就不支持開閉原則,由於要修改建立系列產品的抽象基類AbstractFactory,增長相應產品的建立方法,這也是抽象工廠的缺點所在。

    3、抽象工廠的實現要點

    1)若是沒有應對「多系列對象建立」的需求變化,則沒有必要使用AbstractFactory模式,這時候使用簡單工廠模式徹底能夠。

    2)"系列對象"指的是這些對象之間有相互依賴、或做用的關係,例如遊戲開發場景中「道路」與「房屋」的依賴,「道路」與「地道」的依賴。

    3)AbstractFactory模式主要在於應對「新系列」的需求變更,其缺點在於難以應對「新對象」的需求變更

    4)AbstractFactory模式常常和FactoryMethod模式共同組合來應對「對象建立」的需求變化。

    3.1抽象工廠模式的優勢

    抽象工廠模式將系列產品的建立工做延遲到具體工廠的子類中,咱們聲明工廠類變量的時候使用的是抽象類型,同理,咱們使用產品類型也是抽象類型,

這樣作能夠儘量地減小客戶端代碼與具體產品類之間的依賴,從而下降了系統的耦合度。耦合度下降了,對於後期的維護和擴展就更有利,這就是抽象

工廠模式的優勢所在。

    可能有人會說在Main方法裏面(客戶端)仍是會使用具體的工廠類,對的。這個其實咱們能夠經過.Net配置文件把這部分移出去,把依賴關係放到配置文

件中。若是有新的需求咱們只須要修改配置文件,根本就不須要修改代碼了,讓客戶代碼更穩定。依賴關係確定會存在,咱們要作的就是下降依賴,想徹底

去除很難,也不現實。

    3.2抽象工廠模式的缺點

    有優勢確定就有缺點,由於每種模式都有它的使用範圍,或者說不能解決的問題就是缺點。抽象工廠模式很難支持增長新產品的變化,這是由於抽象工廠

接口中已經肯定了能夠被建立的產品集合,若是須要添加新產品,此時就必須去修改抽象工廠的接口,這樣就涉及到抽象工廠類以及全部子類的改變,這樣

也就違背了開閉原則。

    3.3抽象工廠模式的使用場景

    若是系統須要多套的代碼解決方案,而且每套的代碼方案中又有不少相互關聯的產品類型,而且在系統中能夠相互替換地使用一套產品的時候就可使用

該模式,客戶端不須要依賴具體實現。

    4、.NET中抽象工廠模式實現

    微軟的類庫發展了這麼多年,設計模式在裏面有大量的應用。抽象工廠模式在.NET類庫中也存在着大量的使用,好比和操做數據庫有關的類型,這個類是

System.Data.Common.DbProviderFactory,此類位於System.Data.dll程序集中。該類扮演抽象工廠模式中抽象工廠的角色,咱們能夠用ILSpy反編譯工具查

看該類的實現:

    /// 扮演抽象工廠的角色
    /// 建立鏈接數據庫時所須要的對象集合
    /// 這個對象集合包括有DbConnection對象(抽象產品類)、DbCommand類、DbDataAdapter類,針對不一樣的具體工廠都須要實現該抽象類中的方法。

    public abstract class DbProviderFactory
    {
        public virtual bool CanCreateDataSourceEnumerator
        {
            get
            {
                return false;
            }
        }

        public virtual DbCommand CreateCommand()
        {
            return null;
        }

        public virtual DbCommandBuilder CreateCommandBuilder()
        {
            return null;
        }

        public virtual DbConnection CreateConnection()
        {
            return null;
        }

        public virtual DbConnectionStringBuilder CreateConnectionStringBuilder()
        {
            return null;
        }

        public virtual DbDataAdapter CreateDataAdapter()
        {
            return null;
        }

        public virtual DbParameter CreateParameter()
        {
            return null;
        }

        public virtual CodeAccessPermission CreatePermission(PermissionState state)
        {
            return null;
        }

        public virtual DbDataSourceEnumerator CreateDataSourceEnumerator()
        {
            return null;
        }
    }
View Code

    DbProviderFactory類是一個抽象工廠類,該類提供了建立數據庫鏈接時所須要的對象集合的接口,實際建立工做在其子類工廠中進行。微軟使用的是

SQL Server數據庫,所以提供了鏈接SQL Server數據的具體工廠實現,具體代碼能夠用反編譯工具查看。

    SqlClientFactory扮演着具體工廠的角色,用來建立鏈接SQL Server數據所須要的對象:

    public sealed class SqlClientFactory : DbProviderFactory, IServiceProvider
    {
        public static readonly SqlClientFactory Instance = new SqlClientFactory();

        public override bool CanCreateDataSourceEnumerator
        {
            get
            {
                return true;
            }
        }

        private SqlClientFactory()
        {
        }

        public override DbCommand CreateCommand()
        {
            return new SqlCommand();
        }

        public override DbCommandBuilder CreateCommandBuilder()
        {
            return new SqlCommandBuilder();
        }

        public override DbConnection CreateConnection()
        {
            return new SqlConnection();
        }

        public override DbConnectionStringBuilder CreateConnectionStringBuilder()
        {
            return new SqlConnectionStringBuilder();
        }

        public override DbDataAdapter CreateDataAdapter()
        {
            return new SqlDataAdapter();
        }

        public override DbParameter CreateParameter()
        {
            return new SqlParameter();
        }

        public override CodeAccessPermission CreatePermission(PermissionState state)
        {
            return new SqlClientPermission(state);
        }

        public override DbDataSourceEnumerator CreateDataSourceEnumerator()
        {
            return SqlDataSourceEnumerator.Instance;
        }

        object IServiceProvider.GetService(Type serviceType)
        {
            object result = null;
            if (serviceType == GreenMethods.SystemDataCommonDbProviderServices_Type)
            {
                result = GreenMethods.SystemDataSqlClientSqlProviderServices_Instance();
            }
            return result;
        }
    }
View Code

    OdbcFactory也是具體工廠類:

    public sealed class OdbcFactory : DbProviderFactory
    {
        public static readonly OdbcFactory Instance = new OdbcFactory();

        private OdbcFactory()
        {
        }

        public override DbCommand CreateCommand()
        {
            return new OdbcCommand();
        }

        public override DbCommandBuilder CreateCommandBuilder()
        {
            return new OdbcCommandBuilder();
        }

        public override DbConnection CreateConnection()
        {
            return new OdbcConnection();
        }

        public override DbConnectionStringBuilder CreateConnectionStringBuilder()
        {
            return new OdbcConnectionStringBuilder();
        }

        public override DbDataAdapter CreateDataAdapter()
        {
            return new OdbcDataAdapter();
        }

        public override DbParameter CreateParameter()
        {
            return new OdbcParameter();
        }

        public override CodeAccessPermission CreatePermission(PermissionState state)
        {
            return new OdbcPermission(state);
        }
    }
View Code

    固然,咱們也有OleDbFactory類型,都是負責具體的數據庫操做。DbProviderFactory就是抽象工廠模式UML裏面AbstractFactory類型,其它具體的工廠類

型繼承於DbProviderFactory類型。

    5、總結

    學習設計模式不能死學,要把握核心點和使用場景,關鍵點是面向對象設計模式的基本原則。有了原則,考慮問題就不會跑偏,而後再仔細把握每種模式的

使用場景和要解決的問題,多寫寫代碼,多看看Net的類庫,它是最好的教材。

相關文章
相關標籤/搜索