设计模式三十六计之抽象工厂模式(Abstract Factory)
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()+"\n"+memory.getDescription()+"\n"+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.适用性
当满足以下场景时适合适用抽象工厂模式
- 系统应该独立于其产品的创建、组成和表示方式
- 一个系统应该配置多个产品系列中的一个
- 相关产品对象的系列设计为一起使用,您需要强制执行此约束
- 您希望提供产品的类库,并且只显示它们的接口,而不显示它们的实现
- 您需要一个运行时值来构造一个特定的依赖项
- 您需要提供一个或多个仅在运行时已知的参数,然后才能解析依赖项
[原文链接:https://www.ramostear.com/articles/abstractfactory_design_pattern.html