天天看點

設計模式--抽象工廠(AbstractFactory)抽象工廠模式(AbstractFactory)

抽象工廠模式(AbstractFactory)

工廠方法模式中考慮的是一類産品的生産,如畜牧場隻養動物、電視機廠隻生産電視機、計算機軟體學院隻培養計算機軟體專業的學生等。

同種類稱為同等級,也就是說:工廠方法模式隻考慮生産同等級的産品,但是在現實生活中許多工廠是綜合型的工廠,能生産多等級(種類) 的産品,如農場裡既養動物又種植物,電器廠既生産電視機又生産洗衣機或空調,大學既有軟體專業又有生物專業等。

本節要介紹的抽象工廠模式将考慮多等級産品的生産,将同一個具體工廠所生産的位于不同等級的一組産品稱為一個産品族,圖 1 所示的是海爾工廠和 TCL 工廠所生産的電視機與空調對應的關系圖。

設計模式--抽象工廠(AbstractFactory)抽象工廠模式(AbstractFactory)

模式的定義與特點

  • 抽象工廠(AbstractFactory)模式的定義:

    是一種為通路類提供一個建立一組相關或互相依賴對象的接口,且通路類無須指定所要産品的具體類就能得到同族的不同等級的産品的模式結構。

    抽象工廠模式是工廠方法模式的更新版本,工廠方法模式隻生産一個等級的産品,而抽象工廠模式可生産多個等級的産品。

    使用抽象工廠模式一般要滿足以下條件:

    1.系統中有多個産品族,每個具體工廠建立同一族但屬于不同等級結構的産品。

    2.系統一次隻可能消費其中某一族産品,即同族的産品一起使用。

  • 抽象工廠模式除了具有工廠方法模式的優點外,其他主要優點如下:

    1.可以在類的内部對産品族中相關聯的多等級産品共同管理,而不必專門引入多個新的類來進行管理。

    2.當增加一個新的産品族時不需要修改原代碼,滿足開閉原則。

  • 抽象工廠模式的缺點:

    當産品族中需要增加一個新的産品時,所有的工廠類都需要進行修改。

模式的結構與實作

抽象工廠模式同工廠方法模式一樣,也是由抽象工廠、具體工廠、抽象産品和具體産品等 4 個要素構成,但抽象工廠中方法個數不同,抽象産品的個數也不同。現在我們來分析其基本結構和實作方法。

  • 模式的結構

    抽象工廠模式的主要角色如下。

    1.抽象工廠(Abstract Factory): 提供了建立産品的接口,它包含多個建立産品的方法 newProduct(),可以建立多個不同等級的産品。

    2.具體工廠(Concrete Factory): 主要是實作抽象工廠中的多個抽象方法,完成具體産品的建立。

    3.抽象産品(Product): 定義了産品的規範,描述了産品的主要特性和功能,抽象工廠模式有多個抽象産品。

    4.具體産品(ConcreteProduct): 實作了抽象産品角色所定義的接口,由具體工廠來建立,它 同具體工廠之間是多對一的關系。

    抽象工廠模式的結構圖如圖 2 所示。

    設計模式--抽象工廠(AbstractFactory)抽象工廠模式(AbstractFactory)
  • 模式的實作

    從圖 2 可以看出抽象工廠模式的結構同工廠方法模式的結構相似,不同的是其産品的種類不止一個,是以建立産品的方法也不止一個。下面給出抽象工廠和具體工廠的代碼。

(1) 抽象工廠:提供了産品的生成方法。

interface AbstractFactory
    {
        public Product1 newProduct1();
        public Product2 newProduct2();
    }
           

(2) 具體工廠:實作了産品的生成方法。

class ConcreteFactory1 implements AbstractFactory
    {
        public Product1 newProduct1()
        {
            System.out.println("具體工廠 1 生成-->具體産品 11...");
            return new ConcreteProduct11();
        }
        public Product2 newProduct2()
        {
            System.out.println("具體工廠 1 生成-->具體産品 21...");
            return new ConcreteProduct21();
        }
    }
           

模式的執行個體

我們将建立 Shape 和 Color 接口和實作這些接口的實體類。下一步是建立抽象工廠類 AbstractFactory。接着定義工廠類 ShapeFactory 和 ColorFactory,這兩個工廠類都是擴充了 AbstractFactory。然後建立一個工廠創造器/生成器類 FactoryProducer。

AbstractFactoryPatternDemo,我們的示範類使用 FactoryProducer 來擷取 AbstractFactory 對象。它将向 AbstractFactory 傳遞形狀資訊 Shape(CIRCLE / RECTANGLE / SQUARE),以便擷取它所需對象的類型。同時它還向 AbstractFactory 傳遞顔色資訊 Color(RED / GREEN / BLUE),以便擷取它所需對象的類型。

設計模式--抽象工廠(AbstractFactory)抽象工廠模式(AbstractFactory)

1.為形狀建立一個接口。Shape.java

public interface Shape {
   void draw();
}
           

2.建立實作接口的實體類。Rectangle.java、Square.java、Circle.java

public class Rectangle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

public class Square implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

public class Circle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}
           

3.為顔色建立一個接口。Color.java

public interface Color {
   void fill();
}
           

4.建立實作接口的實體類。Red.java、Green.java、Blue.java

public class Red implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Red::fill() method.");
   }
}

public class Green implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Green::fill() method.");
   }
}

public class Blue implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Blue::fill() method.");
   }
}
           

5.為 Color 和 Shape 對象建立抽象類來擷取工廠。AbstractFactory.java

public abstract class AbstractFactory {
   public abstract Color getColor(String color);
   public abstract Shape getShape(String shape) ;
}
           

6.建立擴充了 AbstractFactory 的工廠類,基于給定的資訊生成實體類的對象。ShapeFactory.java、ColorFactory.java

public class ShapeFactory extends AbstractFactory {
    
   @Override
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }        
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
   
   @Override
   public Color getColor(String color) {
      return null;
   }
}

public class ColorFactory extends AbstractFactory {
    
   @Override
   public Shape getShape(String shapeType){
      return null;
   }
   
   @Override
   public Color getColor(String color) {
      if(color == null){
         return null;
      }        
      if(color.equalsIgnoreCase("RED")){
         return new Red();
      } else if(color.equalsIgnoreCase("GREEN")){
         return new Green();
      } else if(color.equalsIgnoreCase("BLUE")){
         return new Blue();
      }
      return null;
   }
}
           

7.建立一個工廠創造器/生成器類,通過傳遞形狀或顔色資訊來擷取工廠。FactoryProducer.java

public class FactoryProducer {
   public static AbstractFactory getFactory(String choice){
      if(choice.equalsIgnoreCase("SHAPE")){
         return new ShapeFactory();
      } else if(choice.equalsIgnoreCase("COLOR")){
         return new ColorFactory();
      }
      return null;
   }
}
           

8.使用 FactoryProducer 來擷取 AbstractFactory,通過傳遞類型資訊來擷取實體類的對象。AbstractFactoryPatternDemo.java

public class AbstractFactoryPatternDemo {
   public static void main(String[] args) {
 
      //擷取形狀工廠
      AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
 
      //擷取形狀為 Circle 的對象
      Shape shape1 = shapeFactory.getShape("CIRCLE");
 
      //調用 Circle 的 draw 方法
      shape1.draw();
 
      //擷取形狀為 Rectangle 的對象
      Shape shape2 = shapeFactory.getShape("RECTANGLE");
 
      //調用 Rectangle 的 draw 方法
      shape2.draw();
      
      //擷取形狀為 Square 的對象
      Shape shape3 = shapeFactory.getShape("SQUARE");
 
      //調用 Square 的 draw 方法
      shape3.draw();
 
      //擷取顔色工廠
      AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
 
      //擷取顔色為 Red 的對象
      Color color1 = colorFactory.getColor("RED");
 
      //調用 Red 的 fill 方法
      color1.fill();
 
      //擷取顔色為 Green 的對象
      Color color2 = colorFactory.getColor("Green");
 
      //調用 Green 的 fill 方法
      color2.fill();
 
      //擷取顔色為 Blue 的對象
      Color color3 = colorFactory.getColor("BLUE");
 
      //調用 Blue 的 fill 方法
      color3.fill();
   }
}
           

執行程式,輸出結果:

Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside Red::fill() method.
Inside Green::fill() method.
Inside Blue::fill() method.
           

模式的應用場景

抽象工廠模式最早的應用是用于建立屬于不同作業系統的視窗構件。如 java 的 AWT 中的 Button 和 Text 等構件在 Windows 和 UNIX 中的本地實作是不同的。

抽象工廠模式通常适用于以下場景:

  1. 當需要建立的對象是一系列互相關聯或互相依賴的産品族時,如電器工廠中的電視機、洗衣機、空調等。
  2. 系統中有多個産品族,但每次隻使用其中的某一族産品。如有人隻喜歡穿某一個品牌的衣服和鞋。
  3. 系統中提供了産品的類庫,且所有産品的接口相同,用戶端不依賴産品執行個體的建立細節和内部結構。

模式的擴充

抽象工廠模式的擴充有一定的“開閉原則”傾斜性:

  1. 當增加一個新的産品族時隻需增加一個新的具體工廠,不需要修改原代碼,滿足開閉原則。
  2. 當産品族中需要增加一個新種類的産品時,則所有的工廠類都需要進行修改,不滿足開閉原則。
  3. 當系統中隻存在一個等級結構的産品時,抽象工廠模式将退化到工廠方法模式。

繼續閱讀