設計模式之抽象工廠(從模式講到設計模式再到面向對象設計模式)

在講抽象工廠之前,要從模式開始講起
先來看看模式的起源:
   多年以前,有一位名叫克里斯多佛·亞歷山大(英文名Christopher Alexander)的建築師爲了研究優秀的設計有沒有共性這一問題,
他對建築物、城鎮、街道等,以及人類爲自己所建造的各種生活空間進行了大量的觀察。他發現,在特定的建築物中,優秀的結構都有一些共同之處,雖然它們結構互不相同,但可能都具有很高的質量。
    例如:兩個門廊雖然結構上不同,但都具有很高的質量。不同的建築可能是爲了解決不同的問題。一個門廊可能是走道和前門之間的
過渡,而另一個門廊可能是爲了在天氣炎熱時提供陰涼。或許,兩個門廊在解決同一個問題(過渡)時,也可採用不同的方式。亞歷山大看到了這一點,他知道結構不能與要解決的問題分離,因此,在尋找和描述設計質量一致性的探求中,亞歷山大認識到,必須觀察爲了解決同樣問題而設計的不同結構。
   亞歷山大發現,通過這樣的方式——觀察解決相似問題的不同結構,可以縮小關注範圍,從而看清優秀設計之前的相似之處。他將這
種相似之處稱之爲模式。
   他對模式的定義是“在某一環境下某個問題的一種解決方案”。每個模式都描述了一個在我們的環境中會不斷重複出現的問題,並敘
述了這個問題解決方案的要素,通過這種方式,同一解決方案能夠被反覆應用無數次,而每一次使用的具體方式可以不同。
亞歷山大對模式的描述包括如下四項:
1、模式的名稱
2、模式的目的,也就是解決的問題
3、實現方法
4、爲了實現該模式我們必須考慮的限制和約束因素
   在20世紀90年代,軟件界有好多人在想,軟件開發中是否存在以某種相同的方式解決不斷重複出現的問題,是否可以用模式的方法來
設計軟件,經過他們不斷的總結,答案是肯定的。

  以現實生活中“路”的生成爲例:“地上本沒有路,走的人多了便成了路”。同理,設計模式是經驗的總結與傳承。不論是建築設計模式,還是軟件設計模式,這些經驗都源於“人”,所以說人是一個經驗性動物。在我們每天的生活或工作環境中,如果存在一些會影響我們生活或者工作的現象或問題,我們就對這些現象或問題做出一個判斷或處理。這些經驗總結源於實踐,也服務於實踐。從“模式”到“設計模式”,再到“面向對象設計模式”,這是一個從廣泛到具體的過程。“設計模式”是一個廣泛的概念,它既可以指建築中的設計模式,也可以指軟件開發中的設計模式等。“面向對象設計模式”是可複用面向對象軟件的基礎。三者的基本描述如下:
1、每一個模式描述了一個在我們周圍不斷重複發生的問題,以及該問題的解決方案。
2、設計模式描述了軟件開發過程中某一類常見問題的一般性解決方案。
3、面向對象設計模式是對在特定場景下,解決一般設計問題中類與相互通信對象的描述。

目前最有影響力的書籍是:《設計模式:可複用面向對象軟件的基礎》,它共編錄了23種設計模式,分三大類別:創建型模式、結構型模式、行爲模式,其中有一種創建型模式是抽象工廠設計模式。

在學習抽象工廠設計模式之前,要先知道簡單工廠模式
   衆所周知,從結構可以看出,簡單工廠模式中的工廠依賴於所有的子類產品,客戶只需知道父類產品和工廠即可。工廠是整個模式的
核心,以不變應萬變。它雖然使對象的創建與使用進行了分離,但一次只能創建一個對象。它不能實現一次創建一系列相互依賴對象的需求,爲此我們需要學習抽象工廠設計模式。

  打個比方:我想買一個移動硬盤,那麼我只要告訴你硬盤工廠生產一塊120G的移動硬盤就可以了!至於你工廠內如何生產,那不是我關心的問題(哪怕是你工廠能生產40G、80G、160G的,也與我沒有關係),我只要給你工廠一個條件(120G),工廠給我一塊120G的硬盤就可以了,其它的我不想知道,也不需要知道不是嗎?那麼,不難看出,做爲客戶,我們只要知道工廠和父類產品就可以了,還工廠則是提供了一個接口,告訴客戶工廠可以生產移動硬盤!可以看出這個工廠只能生產移動硬盤這種產品!
  現在問題來了,移動硬盤壞了,我還要再一塊硬盤,同時我還想再買一個CPU,再買一個顯示器,那這時怎麼辦,我們要去每個工廠都告訴一下
嗎?答案那是不可能的(因爲我也哪個工廠生產CPU,哪個工廠生產顯示器)。那我們爲什麼不去一個既有CPU賣,又有顯示器賣,還有移動硬盤賣的地方呢? 那麼這時候我們只有有需求就可以被滿足了。這裏我們就把這

種地方抽象爲電腦抽象工廠。電腦這個抽象工廠都是由什麼組成的呢(比如:顯示器、CPU、顯卡、主板、內存、硬盤等),那麼這裏的產品因爲沒有被真正的製作出來,這裏只是知道電腦由什麼組成,所以我們把這樣的產品稱之爲抽象產品。

 

結論:抽象工廠生產抽象產品!

 

  現在,如果一個公司(聯想)成立了,這家公司想打造一個自己的電腦品牌,那麼這家公司就應該有可以生產所有電腦組成所需的產品對吧?(比如:顯示器、CPU、顯卡、主板、內存、硬盤等等,即使不是自己工廠生產的,那麼也要從新把這個產品打上自己的商標),好了,下面開始要生產自己的顯示器了。問題來了,電腦中的顯示器(也就是抽象工廠中的抽象產品)有沒有公有接口或者說是方法呢?一定是有的,比如顯示器都可以顯示吧,都有一個數據線與電腦提供的接口相連接吧等等。這也就要求聯想在生產自己的顯示器的時候要遵循顯示器(抽象產品)的規則。然後在這個基礎上,再增加自己顯示器的功能,以便對抗其它生產商。如果再有一家公司(戴爾)也與聯想的一致.


結論:實體工廠生產實體產品
結論:抽象產品提供實體產品的訪問接口
結論:實體產品實現自己的功能。

如果現在大家還不太明白,那也不要緊,我現在用僞代碼寫一下:


抽象工廠

public abstract class 電腦抽象工廠
{
   //大家都學過用接口做爲返回值類型吧,衆所周知,接口可以做參數傳遞同時也可做爲返回值,這裏不再講解接口.
    public abstract 顯示器抽象產品接口  生產顯示器的方法();
   public abstract CPU抽象產品接口  生產CPU抽象產品();
}

抽象產品
public interface 顯示器抽象產品接口
{
   返回值類型 顯示器裏的方法1();
   返回值類型 顯示器裏的方法2();
}
public interface CPU抽象產品接口
{
   返回值類型 CPU裏的方法1();
   返回值類型 CPU裏的方法2();
}

 

實體工廠
public class 聯想電腦工廠 : 電腦抽象工廠//是由電腦抽象工廠派生的
{
 public override 顯示器抽象產品接口 生產顯示器的方法()//生產聯想顯示器實體產品
        {
            return new 聯想顯示器實體產品();
        }
  public override CPU抽象產品接口 生產CPU抽象產品()//生產聯想CPU實體產品
        {
            return new 聯想CPU實體產品();
        }
}
public class 戴爾電腦工廠 : 電腦抽象工廠//是由電腦抽象工廠派生的
{
 public override 顯示器抽象產品接口 生產顯示器的方法()//生產戴爾顯示器實體產品
        {
            return new 戴爾顯示器實體產品();
        }
  public override CPU抽象產品接口  生產CPU抽象產品()//生產戴爾CPU實體產品
        {
            return new 戴爾CPU實體產品();
        }
}

 

 

實體產品
聯想


public class 聯想顯示器實體產品:顯示器抽象產品接口
{
   public 返回值類型 顯示器裏的方法1()
   {
    //實現
   }
   public 返回值類型 顯示器裏的方法2()
   {
    //實現
   }
}
public class 聯想CPU實體產品:CPU抽象產品接口
{
      public 返回值類型 CPU裏的方法1()
      {
       //實現
      }
      public 返回值類型 CPU裏的方法2()
      {
       //實現
      }
}
戴爾
public class 戴爾顯示器實體產品:顯示器抽象產品接口
{
      public 返回值類型 顯示器裏的方法1()
      {
       //實現
      }
      public 返回值類型 顯示器裏的方法2()
      {
       //實現
      }
}
public class 戴爾CPU實體產品:CPU抽象產品接口
{
      public 返回值類型 CPU裏的方法1()
      {
       //實現
      }
      public 返回值類型 CPU裏的方法2()
      {
       //實現
      }
}

 

如果大家對抽象工廠、抽象產品、實體工廠、實體產品已經能夠理解,那麼請向下看:

 

爲了在調用時方便,我們在抽象工廠里加一個創建實體工廠的方法
public abstract class 電腦抽象工廠
{
 //創建實體工廠
  public static 電腦抽象工廠 選擇實體工廠(string typename)
         {
             電腦抽象工廠 抽象工廠實體 = null;
             switch (typename)
              {
                 case "聯想":
                     抽象工廠實體 = new 聯想電腦工廠();
                     break;
                 case "戴爾":
                     抽象工廠實體 = new 戴爾電腦工廠();
                     break;
              }
             return 抽象工廠實體;
        }
      //大家都學過用接口做爲返回值類型吧,衆所周知,接口可以做參數傳遞同時也可做爲返回值,這裏不再講解接口.
      public abstract 顯示器抽象產品接口  生產顯示器的方法();
      public abstract CPU抽象產品接口  生產CPU抽象產品();
}


這裏在調用的時候就可以這樣使用了
public static void Main()
{
      //電腦抽象工廠 電腦實體=電腦抽象工廠.選擇實體工廠("戴爾");
      電腦抽象工廠 電腦實體=電腦抽象工廠.選擇實體工廠("聯想");
      電腦實體.生產顯示器的方法();
      電腦實體.生產CPU抽象產品();
      //這樣,只要傳入一個品牌,就可以得到這個品牌的電腦了
}

寫這個東東花掉了我一晚上的時間,哎,累~~~~~
對了,大家有時間的話幫我點一下Google的廣告吧,

http://www.jdwzw.cn

http://www.wzydw.cn

我的個人網站,呵呵,謝謝大家!點完後記得

在這裏留名喲,我好回謝!

好了,就寫這些了,文章絕對原創,所以有點亂,思路還不是太好,有錯誤或描述不準的還請大家指正,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章