抽象工廠設計模式(Abstract Factory Design Pattern)

sourcemaking.com

目的:

  • 提供一個接口來創建相關的或有依賴的對象們的家庭,而不用指明他們的具體類。
  • 一種層級結構封裝了:許多可能的“平臺”(比如窗口系統、操作系統、數據庫等),還有構建了一套“產品”。
  • new 操作在這裏認爲是有害的。

問題:

        如果一個應用被認爲是便攜式的,它需要封裝平臺依賴。這些平臺可能包括窗口系統、操作系統、數據庫等。經常,這種封裝並沒有在之前就設計出來,並且代碼中有非常多if判斷來配置不同的支持平臺,就像生產兔子一樣。

討論:

        提供一個間接層來抽象化相關聯的或者有依賴關係的一類對象的創建,而不用具體化類。這個“工廠”對象有責任提供整個平臺家庭的創建相關服務。客戶端從來不用直接創建平臺對象,他們讓工廠幫他們創建。

        這種機制使得交換產品家庭變得簡單,因爲具體的工廠對象類只有在實例化的時候出來一次。應用可以批發式的更換整個產品家庭簡單的通過實例化一個不同的抽象工廠。

        因爲工廠對象提供的服務無處不在,所以通常被實現成單例(Singleton)模式。

結構:

        抽象工廠在每一個產品裏定義了一個工廠方法。每一個工廠方法封裝了new操作和具體的、平臺細化的產品類們。然後每一個”平臺“通過一個工廠衍生出來的類被模具化出來。

例子:

         抽象工廠的目的是爲了提供一個接口來創建相關對象的家庭而不用指明具體類。這種模式被用在日本汽車的片狀金屬衝壓裝置上。衝壓裝置是一個抽象工廠,它製造汽車車身部件。同樣的機器被用來衝壓右車門、左車門、左前擋泥板、右前擋泥板、車頂等等,給不同的車型。通過不同的滾壓機改變衝壓鋼型,機器生產的具體的類可以在三分鐘內改變。

覈對表:

  1. 判斷是否是“平臺獨立的”並且建立服務是當前痛苦來源。
  2. 列一個平臺對產品的矩陣。
  3. 定義一個工廠接口包括每個產品一個工廠方法。
  4. 爲每一個平臺定義一個工廠衍生類,它封裝了所有對new操作的引用。
  5. 客戶端應該淘汰所有對new的引用,改爲用工廠方法建立產品對象。

經驗法則:

  • 有時候Creational Patterns (創建模式)存在競爭關係:有這種情況不管是Prototype、Abstract Factory都可以被有益的使用。還有時他們可以是互補的:抽象工廠可能存一系列的Prototypes來克隆然後返回產品對象,Builder模式可以用另一個模式來實現哪一個組件被建立。Abstract Factory、Builder和Prototype實現時都可以用到Singleton。
  • Abstract Factory、Builder和Prototype定義了一個工廠對象它有責任瞭解建造產品對象的類,並且把它作爲系統的一個參數。抽象工廠有一個工廠對象生產好幾種類的對象。Builder有一個工廠對象用一種相對複雜的協議漸漸地建立一個複雜的產品。Prototype有一個工廠對象(aka prototype)通過複製一個prototype對象來建立一個產品。
  • 抽象工廠類通常通過工廠方法實現,但也可以通過prototype實現。
  • 抽象工廠可以備用來作爲Facade的替代,來隱藏具體平臺的類。
  • Builder關注在一步一步的建立一個複雜的對象。抽象工廠則是注重於一個家庭的產品對象(簡單或複雜)。Builder最後一步才返回產品,而只要抽象工廠被提到,產品就立馬返回。
  • 通常設計從工廠方法(沒那麼複雜、更多的可定製性、生產子類)開始,然後指向抽象工廠、prototype或者Builder(更靈活、更復雜)當設計者發現需要更靈活的地方。

Java示例代碼一:

         抽象工廠類通常是通過工廠方法實現的,但是它也可以通過Prototype模式實現。抽象工廠可以存儲Prototypes的集合然後從它進行克隆和返回產品對象。

  • 工廠方法:通過集成創建。
  • Prototype(雛形?):通過delegation(委派?)創建。
  • 虛擬構造函數:直到運行時才選擇創建的對象。

public class FactoryFmProto
{
    static class Expression
    {
        protected String str;
        public Expression(String s)
        {
            str = s;
        }
        public Expression cloan()
        {
            return null;
        }
        public String toString()
        {
            return str;
        }
    }

    static abstract class Factory
    {
        protected Expression prototype = null;
        public Expression makePhrase()
        {
            return prototype.cloan();
        }
        public abstract Expression makeCompromise();
        public abstract Expression makeGrade();
    }

    static class PCFactory extends Factory
    {
        public PCFactory()
        {
            prototype = new PCPhrase();
        }
        public Expression makeCompromise()
        {
            return new Expression("\"do it your way, any way, or no way\"");
        }
        public Expression makeGrade()
        {
            return new Expression("\"you pass, self-esteem intact\"");
        }
    }

    static class NotPCFactory extends Factory
    {
        public NotPCFactory()
        {
            prototype = new NotPCPhrase();
        }
        public Expression makeCompromise()
        {
            return new Expression("\"my way, or the highway\"");
        }
        public Expression makeGrade()
        {
            return new Expression("\"take test, deal with the results\"");
        }
    }

    public static void main(String[] args)
    {
        Factory factory;
        if (args.length > 0)
            factory = new PCFactory();
        else
            factory = new NotPCFactory();
        for (int i = 0; i < 3; i++)
            System.out.print(factory.makePhrase() + "  ");
        System.out.println();
        System.out.println(factory.makeCompromise());
        System.out.println(factory.makeGrade());
    }

    static class PCPhrase extends Expression
    {
        static String[] list = 
        {
            "\"animal companion\"", "\"vertically challenged\"", 
                "\"factually inaccurate\"", "\"chronologically gifted\""
        };
        private static int next = 0;
        public PCPhrase()
        {
            super(list[next]);
            next = (next + 1) % list.length;
        }
        public Expression cloan()
        {
            return new PCPhrase();
        }
    }

    static class NotPCPhrase extends Expression
    {
        private static String[] list = 
        {
            "\"pet\"", "\"short\"", "\"lie\"", "\"old\""
        };
        private static int next = 0;
        public NotPCPhrase()
        {
            super(list[next]);
            next = (next + 1) % list.length;
        }
        public Expression cloan()
        {
            return new NotPCPhrase();
        }
    }
}

運行結果:

D:\Java\patterns> java FactoryFmProto
"short"  "lie"  "old"
"my way, or the highway"
"take test, deal with the results"

D:\Java\patterns> java FactoryFmProto 1
"vertically challenged"  "factually inaccurate"  "chronologically gifted"
"do it your way, any way, or no way"
"you pass, self-esteem intact"

Java示例代碼二:

public abstract class CPU
{
  ...
} // class CPU

class EmberCPU extends CPU
{
  ...
} // class EmberCPU

class EmberToolkit extends ArchitectureToolkit
{
  public CPU createCPU()
  {
    return new EmberCPU();
  } // createCPU()

  public MMU createMMU()
  {
    return new EmberMMU();
  } // createMMU()
  ...
} // class EmberFactory

public abstract class ArchitectureToolkit
{
  private static final EmberToolkit emberToolkit = new EmberToolkit();
  private static final EnginolaToolkit enginolaToolkit = new EnginolaToolkit();
  ...

  // Returns a concrete factory object that is an instance of the
  // concrete factory class appropriate for the given architecture.
  static final ArchitectureToolkit getFactory(int architecture)
  {
    switch (architecture)
    {
      case ENGINOLA:
        return enginolaToolkit;

      case EMBER:
        return emberToolkit;
        ...
    } // switch
    String errMsg = Integer.toString(architecture);
    throw new IllegalArgumentException(errMsg);
  } // getFactory()

  public abstract CPU createCPU();
  public abstract MMU createMMU();
  ...
} // AbstractFactory
 
public class Client
{
  public void doIt()
  {
    AbstractFactory af;
    af = AbstractFactory.getFactory(AbstractFactory.EMBER);
    CPU cpu = af.createCPU();
    ...
  } // doIt
} // class Client

另外可以參考自己寫的一個例子:

http://blog.csdn.net/xiaobaiooo/article/details/44062599



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