1.设计意图
提供一个接口,用于创建相关或者从属对象的族,而不是指定他们的具体类。以下以生产计算机为例给出UML类图:
2.演示案例
假设我们要生产一台计算机(广义的),一台计算机有一些共同的物件。小型计算机(以手机为例)需要有触控屏、微处理器和小型化的内存条。大型计算机(以PC机为例)需要有显示屏、多核处理器和内存条。计算机的各个部件存在着相互依赖关系。
简而言之
抽象工厂即工厂的工厂,它将单独但相关/依赖的工厂分组在一起而不是指定具体类别的工厂。
维基百科:
抽象工厂模式提供了一种方法来封装一组具有共同主题的单个工厂,而不指定它们的具体类。
3.代码示例
以上述的生产计算机为案例,首选我们需要定义一些部件接口并实现这些部件接口
Memory.java
package com.ramostear.pattern.abstractfactory;/** * @author ramostear * @create-time 2019/1/5 0005-2:23 * @modify by : * @info:[内存接口类] * @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:[手机内存类] * @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:[电脑内存条] * @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; }}
然后,我们定义一个抽象的电子产品生产工厂类并创建两个它的实现类:
ElectronicFactory.java
package com.ramostear.pattern.abstractfactory;/** * @author ramostear * @create-time 2019/1/5 0005-2:32 * @modify by : * @info:[电子设备生产工厂接口类] * @since: */public interface ElectronicFactory { /** * 生产屏幕 * @return */ Screen produceScreen(); /** * 生产内存条 * @return */ Memory produceMemory(); /** * 生产处理器 * @return */ Processor produceProcessor();}
ComputerFactory.java
package com.ramostear.pattern.abstractfactory;/** * @author ramostear * @create-time 2019/1/5 0005-2:40 * @modify by : * @info:[电脑生产工厂] * @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:[手机生产工厂] * @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(); }}
现在我们已经拥有了一个抽象的工厂,它可以让我们生产相关的电子产品部件,即手机工厂可以生产手机屏幕、手机处理器和手机内存条,同样电脑工厂可以生产电脑显示器、电脑内存条和电脑处理器等。我们来简单的测试一下:
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()+""+memory.getDescription()+""+processor.getDescription()); }}
控制台输出:
现在,我们可以为不同的电子产品生产工厂设计一个工厂,即工厂的工厂。本例子中,我们创建一个FacotryMaker类,负责返回PhoneFactory或者ComputerFactory,客户端可以通过FactoryMacker工厂来创建所需的工厂,进而生产不同的电子产品部件(屏幕、处理器、内存条)。
首先定义一个枚举类型的类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;}
然后定义一个生产工厂的工厂类FactoryMacker:
package com.ramostear.pattern.abstractfactory;/** * @author ramostear * @create-time 2019/1/5 0005-4:16 * @modify by : * @info:[工厂创建器:工厂的工厂] * @since: */public class FactoryMacker { /** * 此工厂方法负责创建具体的工厂类 * @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; }}
现在,整个抽象工厂模式案例已经全部实现。最后测试一下我们创建的抽象工厂模式案例:
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.适用性
当满足以下场景时适合适用抽象工厂模式
- 系统应该独立于其产品的创建、组成和表示方式
- 一个系统应该配置多个产品系列中的一个
- 相关产品对象的系列设计为一起使用,您需要强制执行此约束
- 您希望提供产品的类库,并且只显示它们的接口,而不显示它们的实现
- 您需要一个运行时值来构造一个特定的依赖项
- 您需要提供一个或多个仅在运行时已知的参数,然后才能解析依赖项