首頁 >Java >java教程 >Java中的抽象工廠詳解

Java中的抽象工廠詳解

黄舟
黄舟原創
2017-09-15 09:51:501204瀏覽

這篇文章主要為大家詳細介紹了java設計模式之抽象工廠的相關資料,具有一定的參考價值,有興趣的夥伴們可以參考一下

 一、概念

  提供一個建立一系列相關或相互依賴物件的接口,而無需指定它們特定的類別。

二、模式動機

  這一系列物件之間是互相依賴的,相當於一個產品族

 三、模式的結構

透過上圖我們可以清楚的看到抽象工廠模式包含以下4個角色:

  1.抽象工廠角色(AbstractFactory):抽象工廠模式的核心,與具體的商業邏輯無關,通常是一個JAVA介面或抽象類別。

  2.具體工廠角色(Concrete Factory):該角色通常與具體的商業邏輯緊密相關,該角色裡面的工廠方法依據具體的商業邏輯實例化具體的產品並返回,客戶端通過該角色並呼叫該角色的工廠方法,獲得具體產品對象,該角色通常都是一個具體JAVA類別來承擔。

  3.抽象產品角色:擔任這個角色的類別是工廠方法模式所創建的產品的父類,或者他們共同擁有的接口,通常是一個接口或者抽像類。

  4.具體產品角色:抽象工廠模式所創造的任何產品都是這個角色的實例,有一個具體JAVA類別來承擔。

範例程式碼如下:


public class AbstractProductA 
{
  
  /**
  * @roseuid 59AC05990327
  */
  public AbstractProductA() 
  {
  
  }
}


public class ProductA1 extends AbstractProductA 
{
  
  /**
  * @roseuid 59AC05990359
  */
  public ProductA1() 
  {
  
  }
}


public class ProductA2 extends AbstractProductA 
{
  
  /**
  * @roseuid 59AC05990381
  */
  public ProductA2() 
  {
  
  }
}

public class AbstractProductB 
{
  
  /**
  * @roseuid 59AC059903BA
  */
  public AbstractProductB() 
  {
  
  }
}

public class ProductB1 extends AbstractProductB 
{
  
  /**
  * @roseuid 59AC059A001F
  */
  public ProductB1() 
  {
  
  }
}

public class ProductB2 extends AbstractProductB 
{
  
  /**
  * @roseuid 59AC059A0049
  */
  public ProductB2() 
  {
  
  }
}


public abstract class AbstractFactory 
{
  
  /**
  * @roseuid 59AC05690005
  */
  public AbstractFactory() 
  {
  
  }
  
  /**
  * @return AbstractProductA
  * @roseuid 59ABFB0103BE
  */
  public Abstract AbstractProductA createProductA() ;
  
  
  /**
  * @return AbstractProductB
  * @roseuid 59ABFB3B029D
  */
  public Abstract AbstractProductB createProductB() ;
}


public class ConcreteFactory1 extends AbstractFactory 
{
  
  /**
  * @roseuid 59AC057A02FC
  */
  public ConcreteFactory1() 
  {
  
  }
  
  /**
  * @return AbstractProductA
  * @roseuid 59ABFB9C00C9
  */
  public AbstractProductA createProductA() 
  {
    return new ProductA1();
  }
  
  /**
  * @return AbstractProductB
  * @roseuid 59ABFBA30011
  */
  public AbstractProductB createProductB() 
  {
    return new ProductB1();
  }
}



public class ConcreteFactory2 extends AbstractFactory 
{
  
  /**
  * @roseuid 59AC057A02C0
  */
  public ConcreteFactory2() 
  {
  
  }
  
  /**
  * @return AbstractProductA
  * @roseuid 59ABFCC701B9
  */
  public AbstractProductA createProductA() 
  {
    return new ProductA2();
  }
  
  /**
  * @return AbstractProductB
  * @roseuid 59ABFCC9001F
  */
  public AbstractProductB createProductB() 
  {
    return new ProductB2();
  }
}


public class Client 
{
  
  
  /**
  * @roseuid 59AC055700AB
  */
  public Client() 
  {
  
  }

  public static void main(String[] args){
      AbstractFactory theAbstractFactory;
    AbstractProductA theAbstractProductA;
    AbstractProductB theAbstractProductB;

    theAbstractFactory=new ConcreteFactory1();

    theAbstractProductA=theAbstractFactory.createProductA();
    theAbstractProductB=theAbstractFactory.createProductB();
 
  }
}

  跟據上面的模式結構圖我們對「提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們特定的類別」  進行一個簡要的分析:

       1.相關或相互依賴對象,在這裡面ProductA1的實例和ProductB1的實例就是一組相互關聯(如內在的關聯關係)或相互依賴(如整體和部分)關係,依據業務邏輯,ProductA1

 只能和同一產品等級結構AbstractProductB下的ProductB1相互關聯而無法與ProductB2關聯在一起。

  2.提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類,這裡面的接口,即為結構圖中的AbstractProductA和AbstractProductB,客戶端只依賴這些產品的介面進行編程,而不依賴具體實現,即符合依賴倒轉原則。 「無需指定它們特定的類別」  即客戶端(client)跟本就不知道ProductA1、ProductA2、ProductB1和ProductB2的存在,客戶端只需要呼叫特定工廠的工廠方法即可傳回特定的產品實例。

四、模式範例

  我們接著工廠方法模式中的範例進行進一步分析,現在這個生產輪胎的工廠已經不滿足只生產轎車輪胎了,他現在已經引入了發動機的生產線(EngineLine)、車門(DoorLine)等整個車的各種零件生產線,可以說他現在可以輕鬆製造一部Car,但是也並非所有的Car都能製造,比如他現只能生產benz和BMW兩種類型的車(這樣的工廠也夠NX了),例如現在一輛車只包含車輪胎、車門和引擎(當然肯定不只這麼多),那麼這個工廠就可以跟據客戶的要求生產BMW和benz車了,如下圖:

#程式碼如下:  


public interface Door {
  public void open();
  public void close();
}
public class BenzDoor implements Door {

  @Override
  public void open() {
    System.out.println("奔驰车门开");
  }

  @Override
  public void close() {
    System.out.println("奔驰车门关");
  }
}
public class BmwDoor implements Door {

  @Override
  public void open() {
    System.out.println("宝马车门开");
  }

  @Override
  public void close() {
    System.out.println("宝马车门关");
  }

}
public interface Tire {
  public void getColor();
  public void getLife();
  public void getWidth();
}
public class BenzTire implements Tire {

  @Override
  public void getColor() {
    System.out.println("benz车color");
  }

  @Override
  public void getLife() {
    System.out.println("benz车life");
  }

  @Override
  public void getWidth() {
    System.out.println("benz车width");
  }
}
public class BmwTire implements Tire {

  @Override
  public void getColor() {
    System.out.println("bmw车color");
  }

  @Override
  public void getLife() {
    System.out.println("bmw车life");
  }

  @Override
  public void getWidth() {
    System.out.println("bmw车width");
  }

}
public interface Engine {
  public void start();

  public void stop();

}
public class BenzEngine implements Engine {

  @Override
  public void start() {
    System.out.println("benz车start");

  }

  @Override
  public void stop() {
    System.out.println("benz车stop");

  }

}
public class BmwEngine implements Engine {

  @Override
  public void start() {
    System.out.println("bmw车start");

  }

  @Override
  public void stop() {
    System.out.println("bmw车stop");

  }

}
public interface PartFactory {
  public Door createDoor();

  public Tire createTire();

  public Engine createEngine();

}
public class BenzPartFactory implements PartFactory {

  @Override
  public Door createDoor() {
    return new BenzDoor();
  }

  @Override
  public Tire createTire() {
    return new BenzTire();
  }

  @Override
  public Engine createEngine() {
    return new BenzEngine();
  }

}
public class BmwPartFactory implements PartFactory {

  @Override
  public Door createDoor() {
    return new BmwDoor();
  }

  @Override
  public Tire createTire() {
    return new BmwTire();
  }

  @Override
  public Engine createEngine() {
    return new BmwEngine();
  }

}
public class Car {
  private Door door;
  private Engine engine;
  private Tire tire;

  public Car(PartFactory factory) {
    this.door = factory.createDoor();
    this.engine = factory.createEngine();
    this.tire = factory.createTire();
  }

  public Door getDoor() {
    return door;
  }

  public Engine getEngine() {
    return engine;
  }

  public Tire getTire() {
    return tire;
  }  
}
public class Client {
  
  public static void main(String[] args) {
    PartFactory partFactory=new BenzPartFactory();
    Car benzCar=new Car(partFactory);
    
    benzCar.getDoor().open();
    benzCar.getEngine().start();
    benzCar.getTire().getColor();
    
  }

}

#運行結果如下:

  賓士車門開
  benz車start
  benz車color

跟據上面的類別圖及運作結果可以做如下分析:

   BenzTire和BenzEngine有很強的關聯關係,我們可以說一輛benz車,不可能用Bmw的車門,也就是BmwDoor。這種很強的關聯關係透過BenzPartFactory進行了很好的維護。對於客戶端來說,如上面的client類,如果客戶想要一部benz車,那麼我只需要一個生產benz車的工廠即可,這個工廠所有的產品實例,都是benz車的部件。從運行結果我們也可以看出。

         試想一下,隨著這個工廠的發展,他現在也要生產Audi的車,這時我們只要增加一個audi的車門的類AudiDoor、AudiTire 、AudiEngine和AudiPartFactory就可以做任何的修改。但客戶說,我要在車上裝一對翅膀呢,堵車時可以飛,這時我們就要對每個工廠都要增加能返回翅膀的工廠方法,要對每個工廠進行修改,這是不符合開閉原則的。所以說抽象工廠對增加產品等級結構方面是不支持開閉原則的,對於產品族維度(如audi車)是支持開閉原則的。

 五、模式的限制

  對於產生一個相互關聯或依賴的產品族適用,且支援在產品族方向的擴展,不適用於產品等級方向的擴展。

六、模式的變體與擴展

  1、抽像工廠提供靜態工廠方法:抽象工廠可以提供一個靜態的工廠方法,透過參數返回具體的工廠實例。

  2、抽象工廠與具體工廠合併:如果在產品族方向上確定只有一個產品族,那麼抽像工廠就沒有必要了,這時只需要一個具體工廠就可以了,我們可以進一步延深,為這個具體工廠提供一個靜態方法,該方法傳回自已的實例。

七、與其它模式的關係

  如果只有一個產品等級結構,那麼就是工廠方法模式了,如下圖:   

#  如果有多個產品等級結構,那麼抽像工廠裡面的每一個工廠方法都是"工廠方法"模式。

八、模式優缺點

   在產口族方向支持開閉原則,在產口等級結構方向不支持開閉原則。

以上是Java中的抽象工廠詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn