設(shè)計模式三十六計之抽象工廠模式(Abstract Factory)
1.設(shè)計意圖
提供一個接口,用于創(chuàng)建相關(guān)或者從屬對象的族佃迄,而不是指定他們的具體類地淀。以下以生產(chǎn)計算機為例給出UML類圖:
2.演示案例
假設(shè)我們要生產(chǎn)一臺計算機(廣義的)梧疲,一臺計算機有一些共同的物件擦耀。小型計算機(以手機為例)需要有觸控屏、微處理器和小型化的內(nèi)存條榕酒。大型計算機(以PC機為例)需要有顯示屏胚膊、多核處理器和內(nèi)存條故俐。計算機的各個部件存在著相互依賴關(guān)系。
簡而言之
抽象工廠即工廠的工廠紊婉,它將單獨但相關(guān)/依賴的工廠分組在一起而不是指定具體類別的工廠药版。
維基百科:
抽象工廠模式提供了一種方法來封裝一組具有共同主題的單個工廠,而不指定它們的具體類喻犁。
3.代碼示例
以上述的生產(chǎn)計算機為案例槽片,首選我們需要定義一些部件接口并實現(xiàn)這些部件接口
Memory.java
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-2:23
* @modify by :
* @info:[內(nèi)存接口類]
* @since:
*/
public interface Memory {
String getDescription();
}
Screen.java
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-2:22
* @modify by :
* @info:[屏幕接口類]
* @since:
*/
public interface Screen {
String getDescription();
}
Processor.java
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-2:24
* @modify by :
* @info:[處理器接口類]
* @since:
*/
public interface Processor {
String getDescription();
}
PhoneMemory.java
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-2:28
* @modify by :
* @info:[手機內(nèi)存類]
* @since:
*/
public class PhoneMemory implements Memory{
static final String DESCRIPTION = "This is phone memory";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
PhoneScreen.java
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-2:26
* @modify by :
* @info:[手機屏幕類]
* @since:
*/
public class PhoneScreen implements Screen{
static final String DESCRIPTION = "This is phone screen";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
PhoneProcessor.java
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-2:29
* @modify by :
* @info:[手機處理器類]
* @since:
*/
public class PhoneProcessor implements Processor{
static final String DESCRIPTION = "This is phone processor";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
ComputerMomory.java
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-2:38
* @modify by :
* @info:[電腦內(nèi)存條]
* @since:
*/
public class ComputerMemory implements Memory{
static final String DESCRIPTION = "This is computer memory";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
ComputerScreen.java
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-2:36
* @modify by :
* @info:[電腦屏幕]
* @since:
*/
public class ComputerScreen implements Screen{
static final String DESCRIPTION = "This is computer screen";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
ComputerProcessor.java
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-2:39
* @modify by :
* @info:[電腦處理器]
* @since:
*/
public class ComputerProcessor implements Processor{
static final String DESCRIPTION = "This is computer processor";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
然后,我們定義一個抽象的電子產(chǎn)品生產(chǎn)工廠類并創(chuàng)建兩個它的實現(xiàn)類:
ElectronicFactory.java
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-2:32
* @modify by :
* @info:[電子設(shè)備生產(chǎn)工廠接口類]
* @since:
*/
public interface ElectronicFactory {
/**
* 生產(chǎn)屏幕
* @return
*/
Screen produceScreen();
/**
* 生產(chǎn)內(nèi)存條
* @return
*/
Memory produceMemory();
/**
* 生產(chǎn)處理器
* @return
*/
Processor produceProcessor();
}
ComputerFactory.java
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-2:40
* @modify by :
* @info:[電腦生產(chǎn)工廠]
* @since:
*/
public class ComputerFactory implements ElectronicFactory{
@Override
public Screen produceScreen() {
return new ComputerScreen();
}
@Override
public Memory produceMemory() {
return new ComputerMemory();
}
@Override
public Processor produceProcessor() {
return new ComputerProcessor();
}
}
PhoneFactory.java
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-2:35
* @modify by :
* @info:[手機生產(chǎn)工廠]
* @since:
*/
public class PhoneFactory implements ElectronicFactory{
@Override
public Screen produceScreen() {
return new PhoneScreen();
}
@Override
public Memory produceMemory() {
return new PhoneMemory();
}
@Override
public Processor produceProcessor() {
return new PhoneProcessor();
}
}
現(xiàn)在我們已經(jīng)擁有了一個抽象的工廠株汉,它可以讓我們生產(chǎn)相關(guān)的電子產(chǎn)品部件筐乳,即手機工廠可以生產(chǎn)手機屏幕、手機處理器和手機內(nèi)存條乔妈,同樣電腦工廠可以生產(chǎn)電腦顯示器、電腦內(nèi)存條和電腦處理器等氓皱。我們來簡單的測試一下:
public class SimpleTest {
public static void main(String[] args){
ElectronicFactory factory = new PhoneFactory();
Screen screen = factory.produceScreen();
Memory memory = factory.produceMemory();
Processor processor = factory.produceProcessor();
System.out.println(screen.getDescription()+"\n"+memory.getDescription()+"\n"+processor.getDescription());
}
}
控制臺輸出:
現(xiàn)在路召,我們可以為不同的電子產(chǎn)品生產(chǎn)工廠設(shè)計一個工廠,即工廠的工廠波材。本例子中股淡,我們創(chuàng)建一個FacotryMaker類,負(fù)責(zé)返回PhoneFactory或者ComputerFactory,客戶端可以通過FactoryMacker工廠來創(chuàng)建所需的工廠廷区,進而生產(chǎn)不同的電子產(chǎn)品部件(屏幕唯灵、處理器、內(nèi)存條)隙轻。
首先定義一個枚舉類型的類FactoryType,用于給FactoryMacker提供選擇參考:
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-4:16
* @modify by :
* @info:[工廠類型]
* @since:
*/
public enum FactoryType {
PHONE,COMPUTER;
}
然后定義一個生產(chǎn)工廠的工廠類FactoryMacker:
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-4:16
* @modify by :
* @info:[工廠創(chuàng)建器:工廠的工廠]
* @since:
*/
public class FactoryMacker {
/**
* 此工廠方法負(fù)責(zé)創(chuàng)建具體的工廠類
* @param type
* @return
*/
public static ElectronicFactory makeFactory(FactoryType type){
switch (type){
case PHONE:
return new PhoneFactory();
case COMPUTER:
return new ComputerFactory();
default:
throw new IllegalArgumentException("FactoryType not supported.");
}
}
}
最后埠帕,我們定義一個AbstractFactory類來封裝上述的單個工廠類:
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-4:21
* @modify by :
* @since:
*/
public class AbstractFactory {
private Screen screen;
private Memory memory;
private Processor processor;
public void createFactory(final ElectronicFactory factory){
setScreen(factory.produceScreen());
setMemory(factory.produceMemory());
setProcessor(factory.produceProcessor());
}
public Screen getScreen() {
return screen;
}
private void setScreen(Screen screen) {
this.screen = screen;
}
public Memory getMemory() {
return memory;
}
private void setMemory(Memory memory) {
this.memory = memory;
}
public Processor getProcessor() {
return processor;
}
private void setProcessor(Processor processor) {
this.processor = processor;
}
}
現(xiàn)在,整個抽象工廠模式案例已經(jīng)全部實現(xiàn)玖绿。最后測試一下我們創(chuàng)建的抽象工廠模式案例:
package com.ramostear.pattern.abstractfactory;
/**
* @author ramostear
* @create-time 2019/1/5 0005-4:27
* @modify by :
* @info:[對抽象工廠進行測試]
* @since:
*/
public class TestAbstractFactory {
public static void main(String[] args){
AbstractFactory factory = new AbstractFactory();
System.out.println("produce phone...");
factory.createFactory(FactoryMacker.makeFactory(FactoryType.PHONE));
System.out.println(factory.getScreen().getDescription());
System.out.println(factory.getMemory().getDescription());
System.out.println(factory.getProcessor().getDescription());
System.out.println("produce computer...");
factory.createFactory(FactoryMacker.makeFactory(FactoryType.COMPUTER));
System.out.println(factory.getScreen().getDescription());
System.out.println(factory.getMemory().getDescription());
System.out.println(factory.getProcessor().getDescription());
}
}
控制臺輸出:
4.適用性
當(dāng)滿足以下場景時適合適用抽象工廠模式
- 系統(tǒng)應(yīng)該獨立于其產(chǎn)品的創(chuàng)建敛瓷、組成和表示方式
- 一個系統(tǒng)應(yīng)該配置多個產(chǎn)品系列中的一個
- 相關(guān)產(chǎn)品對象的系列設(shè)計為一起使用,您需要強制執(zhí)行此約束
- 您希望提供產(chǎn)品的類庫斑匪,并且只顯示它們的接口呐籽,而不顯示它們的實現(xiàn)
- 您需要一個運行時值來構(gòu)造一個特定的依賴項
- 您需要提供一個或多個僅在運行時已知的參數(shù),然后才能解析依賴項
[原文鏈接:https://www.ramostear.com/articles/abstractfactory_design_pattern.html