在上一篇的工廠模式中中茉贡,工廠生產(chǎn)出來的產(chǎn)品都是實(shí)現(xiàn)同一個(gè)接口或繼承同一個(gè)抽象類的嗽仪。而有時(shí)候工廠可以生產(chǎn)出不是同一個(gè)接口或抽象類的產(chǎn)品锡垄,也就是說生產(chǎn)出來的產(chǎn)品是不確定的破镰,就是抽象工廠了。
定義
為創(chuàng)建一組相關(guān)或相互依賴的對(duì)象提供一個(gè)接口默辨,而無需指定他們的具體類德频。
使用場景
適用于當(dāng)一組產(chǎn)品族之間有互相約束的時(shí)候。它的起源就來與這種模式缩幸,期初是解決不同操作系統(tǒng)的圖形化解決方案壹置。Windows和Linux是兩個(gè)系統(tǒng)竞思,可以看出兩個(gè)產(chǎn)品族,但里面的按鈕和文本要統(tǒng)一風(fēng)格钞护,他們有個(gè)字的產(chǎn)品等級(jí)盖喷。這就有了約束。
由上面可以看出UML圖了
AbstractFactory:抽象工廠角色难咕,聲明了一組用于創(chuàng)建一種產(chǎn)品的方法课梳,每個(gè)方法對(duì)應(yīng)生產(chǎn)一種產(chǎn)品,上面生成產(chǎn)品A和B余佃。
ConcreteFactory:具體工廠角色暮刃,實(shí)現(xiàn)了抽象工廠中定義的創(chuàng)建產(chǎn)品的方法,生成一組具體的產(chǎn)品爆土,每一個(gè)產(chǎn)品又位于某個(gè)產(chǎn)品等級(jí)中椭懊。
AbstractProduct:抽象產(chǎn)品角色,定義了每種產(chǎn)品應(yīng)有的方法
ConcreteProduct:具體的產(chǎn)品角色雾消,具體了工廠生產(chǎn)的具體獨(dú)享灾搏,實(shí)現(xiàn)抽象產(chǎn)品中聲明的方法挫望。
模板
抽象工廠:
public abstract class AbstractFactory {
public abstract AbstractProductA createProductA();
public abstract AbstractProductB createProductB();
}
具體的工廠1和2
public class ConcreteFactory1 extends AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB1();
}
}
public class ConcreteFactory2 extends AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB2();
}
}
抽象的產(chǎn)品A和B
public abstract class AbstractProductA {
public abstract void method();
}
public abstract class AbstractProductB {
public abstract void method();
}
具體的產(chǎn)品A1立润,A2,B1媳板,B2
public class ConcreteProductA1 extends AbstractProductA {
@Override
public void method() {
System.out.println("產(chǎn)品A1的方法");
}
}
public class ConcreteProductA2 extends AbstractProductA {
@Override
public void method() {
System.out.println("產(chǎn)品A2的方法");
}
}
public class ConcreteProductB1 extends AbstractProductB {
@Override
public void method() {
System.out.println("產(chǎn)品B1的方法");
}
}
public class ConcreteProductB2 extends AbstractProductB {
@Override
public void method() {
System.out.println("產(chǎn)品B2的方法");
}
}
簡單實(shí)現(xiàn)
還是以車為例桑腮,上一次的奧迪用工廠模式生產(chǎn)了Q3,Q7蛉幸,但是他們的零件又有差別破讨,Q3的發(fā)動(dòng)機(jī)是國產(chǎn)的,輪胎是鐵的奕纫。Q7的發(fā)動(dòng)機(jī)是外國的提陶,輪胎是塑料的。不同的輪胎匹层,不同的發(fā)動(dòng)機(jī)隙笆,都也是一種產(chǎn)品類型,這時(shí)候就能用抽象產(chǎn)品模式:
汽車首先由生產(chǎn)輪胎升筏,發(fā)動(dòng)機(jī)撑柔,然后組裝成汽車。
抽象的工廠類聲明要生產(chǎn)兩種產(chǎn)品:
public abstract class CarFactory {
public abstract ITire createTire();
public abstract IEngine createEngine();
}
輪胎類:
interface ITire {
void tire();
}
public class FerricFTire implements ITire {
@Override
public void tire() {
System.out.println("鐵輪胎");
}
}
public class PlasticTire implements ITire {
@Override
public void tire() {
System.out.println("塑料輪胎");
}
}
引擎類:
interface IEngine {
void engine();
}
public class DomesticEngine implements IEngine {
@Override
public void engine() {
System.out.println("國產(chǎn)引擎");
}
}
public class ImportIEngine implements IEngine {
@Override
public void engine() {
System.out.println("進(jìn)口引擎");
}
}
具體工廠類
public class Q3Factory extends CarFactory {
@Override
public ITire createTire() {
return new FerricFTire();
}
@Override
public IEngine createEngine() {
return new DomesticEngine();
}
}
public class Q7Factory extends CarFactory {
@Override
public ITire createTire() {
return new PlasticTire();
}
@Override
public IEngine createEngine() {
return new ImportIEngine();
}
}
客戶端調(diào)用:
public class Client {
public static void main(String[] args) {
CarFactory Q3 = new Q3Factory();
Q3.createEngine().engine();
Q3.createTire().tire();
System.out.println("===");
CarFactory Q7 = new Q7Factory();
Q7.createEngine().engine();
Q7.createTire().tire();
}
}
輸出:
國產(chǎn)引擎
鐵輪胎
===
進(jìn)口引擎
塑料輪胎
總結(jié)
抽象工廠模式用的并不多您访,它和簡單工廠和工廠模式的行為很相近铅忿,一般在開發(fā)中用工廠模式就可以解決問題。而且這幾種模式之間可以很隱晦的轉(zhuǎn)換灵汪,所以在用的時(shí)候不用特別在意是哪一種工廠模式檀训,只要能達(dá)到解耦的目的就行
優(yōu)點(diǎn)
- 也是實(shí)現(xiàn)了解耦柑潦,客戶按抽象工廠進(jìn)行生產(chǎn),不需要知道具體的實(shí)現(xiàn)是誰峻凫。
- 但是在產(chǎn)品等級(jí)上加了一個(gè)約束妒茬,便于管理。
缺點(diǎn)
要新家一個(gè)產(chǎn)品的時(shí)候要改動(dòng)非常多的對(duì)象蔚晨,而且要新增一大堆的文件乍钻。因?yàn)槊吭黾右粋€(gè)產(chǎn)品都要修改抽象類,所以他的實(shí)現(xiàn)類也要進(jìn)行相應(yīng)的修改铭腕。