java設(shè)計模式之抽像工廠詳解
一、概念
提供一個創(chuàng)建一系列相關(guān)或相互依賴對像的接口,而無需指定它們具體的類。
二、模式動機
這一系列對像之間是相互依賴的,相當(dāng)于一個產(chǎn)品族
三、模式的結(jié)構(gòu)

通過上圖我們可以清楚的看到抽像工廠模式包括以下4個角色:
1.抽像工廠角色(AbstractFactory):抽像工廠模式的核心,與具體的商業(yè)邏輯無關(guān),通常是一個JAVA接口或者抽像類。
2.具體工廠角色(Concrete Factory):該角色通常與具體的商業(yè)邏輯緊密相關(guān),該角色里面的工廠方法依據(jù)具體的商業(yè)邏輯實例化具體的產(chǎn)品并返回,客戶端通過該角色并調(diào)用該角色的工廠方法,獲得具體產(chǎn)品對像,該角色通常都是一個具體JAVA類來承擔(dān)。
3.抽像產(chǎn)品角色:擔(dān)任這個角色的類是工廠方法模式所創(chuàng)建的產(chǎn)品的父類,或者他們共同擁有的接口,通常是一個接口或者抽像類。
4.具體產(chǎn)品角色:抽像工廠模式所創(chuàng)建的任何產(chǎn)品都是這個角色的實例,有一個具體JAVA類來承擔(dān)。
樣例代碼如下:
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();
}
}
跟據(jù)上面的模式結(jié)構(gòu)圖我們對“提供一個創(chuàng)建一系列相關(guān)或相互依賴對像的接口,而無需指定它們具體的類” 進行一個簡要的分析:
1.相關(guān)或相互依賴對像,在這里面ProductA1的實例和ProductB1的實例就是一組相互關(guān)聯(lián)(如內(nèi)在的關(guān)聯(lián)關(guān)系)或相互依賴(如整體和部分)關(guān)系,依據(jù)業(yè)務(wù)邏輯,ProductA1
只能和同一產(chǎn)品等級結(jié)構(gòu)AbstractProductB下的ProductB1相互關(guān)聯(lián)而無法與ProductB2關(guān)聯(lián)在一起。
2.提供一個創(chuàng)建一系列相關(guān)或相互依賴對像的接口,而無需指定它們具體的類,這里面的接口,即為結(jié)構(gòu)圖中的AbstractProductA和AbstractProductB,客戶端只依賴這些產(chǎn)品的接口進行編程,而不依賴于具體實現(xiàn),即符合依賴倒轉(zhuǎn)原則?!盁o需指定它們具體的類” 即客戶端(client)跟本就不知道ProductA1、ProductA2、ProductB1和ProductB2的存在,客戶端只需要調(diào)用具體工廠的工廠方法即可返回具體的產(chǎn)品實例。
四、模式樣例
我們接著工廠方法模式中的樣例進行進一步分析,現(xiàn)在這個生產(chǎn)輪胎的工廠已經(jīng)不滿足只生產(chǎn)轎車輪胎了,他現(xiàn)已經(jīng)引入了發(fā)動機的生產(chǎn)線(EngineLine)、車門(DoorLine)等整個車的各種零部件生產(chǎn)線,可以說他現(xiàn)在可以輕松制造一部Car,但是也并非所有的Car都能制造,比如他現(xiàn)只能生產(chǎn)benz和BMW兩種類型的車(這樣的工廠也夠NX了),比如現(xiàn)在一部車只包含車輪胎、車門和發(fā)動機(當(dāng)然肯定不止這么多),那么這個工廠就可以跟據(jù)客戶的要求生產(chǎn)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("奔馳車門關(guān)");
}
}
public class BmwDoor implements Door {
@Override
public void open() {
System.out.println("寶馬車門開");
}
@Override
public void close() {
System.out.println("寶馬車門關(guān)");
}
}
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();
}
}
運行結(jié)果如下:
奔馳車門開
benz車start
benz車color
跟據(jù)上面的類圖及運行結(jié)果可以做如下分析:
BenzDoor、BenzTire和BenzEngine有很強的關(guān)聯(lián)關(guān)系,我們可以說一部benz車,不可能用Bmw的車門,即BmwDoor。這種很強的關(guān)聯(lián)關(guān)系通過BenzPartFactory進行了很好的維護。對于客戶端來說,如上面的client類,如果客戶想要一部benz車,那么我只需要一個生產(chǎn)benz車的工廠即可,這個工廠所有的產(chǎn)品實例,都是benz車的部件。從運行結(jié)果我們也可以看出。
試想一下,隨著這個工廠的發(fā)展,他現(xiàn)在也要生產(chǎn)Audi的車,這時我們只要增加一個audi的車門的類AudiDoor、AudiTire 、AudiEngine和AudiPartFactory就可以了,其它的類不需要做任何的修改。但客戶說,我要在車上裝一對翅膀呢,堵車時可以飛,這時我們就要對每個工廠都要增加能返回翅膀的工廠方法,要對每個工廠進行修改,這是不符合開閉原則的。所以說抽象工廠對增加產(chǎn)品等級結(jié)構(gòu)方面是不支持開閉原則的,對于產(chǎn)品族維度(如audi車)是支持開閉原則的。
五、模式的約束
對于產(chǎn)生一個相互關(guān)聯(lián)或依賴的產(chǎn)品族適用,且支持在產(chǎn)品族方向的擴展,不適用于產(chǎn)品等級方向的擴展。
六、模式的變體與擴展
1、抽像工廠提供靜態(tài)工廠方法:抽像工廠可以提供一個靜態(tài)的工廠方法,通過參數(shù)返回具體的工廠實例。
2、抽像工廠與具體工廠合并:如果在產(chǎn)品族方向上確定只有一個產(chǎn)品族,那么抽像工廠就沒有必要了,這時只需要一個具體工廠就可以了,我們可以進一步延深,為這個具體工廠提供一個靜態(tài)方法,該方法返回自已的實例。
七、與其它模式的關(guān)系
如果只有一個產(chǎn)品等級結(jié)構(gòu),那么就是工廠方法模式了,如下圖:

如果有多個產(chǎn)品等級結(jié)構(gòu),那么抽像工廠里面的每一個工廠方法都是"工廠方法"模式。
八、模式優(yōu)缺點
在產(chǎn)口族方向支持開閉原則,在產(chǎn)口等級結(jié)構(gòu)方向不支持開閉原則。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JAVA實現(xiàn)基于Tcp協(xié)議的簡單Socket通信實例
本篇文章主要介紹了JAVA實現(xiàn)基于Tcp協(xié)議的簡單Socket通信實例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01
Java獲取Prometheus監(jiān)控數(shù)據(jù)的方法實現(xiàn)
本文主要介紹了Java獲取Prometheus監(jiān)控數(shù)據(jù)的方法實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-12-12
淺談Mybatis中resultType為hashmap的情況
這篇文章主要介紹了淺談Mybatis中resultType為hashmap的情況,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
Mybatis中的游標(biāo)查詢Cursor(滾動查詢)
這篇文章主要介紹了Mybatis中的游標(biāo)查詢Cursor(滾動查詢),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01
java?MultipartFile文件上傳重命名詳細代碼示例
在文件上傳功能開發(fā)中,為防止文件重名導(dǎo)致數(shù)據(jù)覆蓋,常見的做法是在文件名前加上UUID或時間戳來區(qū)分,這篇文章主要介紹了java?MultipartFile?multipartFile文件上傳重命名的相關(guān)資料,需要的朋友可以參考下2024-09-09

