定义
提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。
为了更清晰地理解工厂方法模式,需要先了解两个概念:
- 产品等级结构 :产品等级结构即产品的继承结构,如一个抽象类是CPU芯片,其子类有英特尔芯片,AMD芯片,则抽象CPU芯片与具体品牌的CPU芯片之间构成了一个产品等级结构,抽象芯片机是父类,而具体品牌的芯片是其子类。
- 产品族 :产品族是指由同一个工厂生产的,但是属于不同产品等级结构中的一组产品,例如AMD生产的AMD显卡,AMD CPU芯片,分别属于显卡,CPU芯片产品等级结构
当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式。
抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。
抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建 。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。
类图
优缺点
优点
- 封装性,只要知道工厂类是谁,我就能创建出一个需要的对象,不需要底层是怎么实现的;
- 产品族内的约束为非公开状态。具体的产品族内的约束是在工厂内实现的,比如显卡和CPU的生产要1:1;
- 增加新的具体工厂和产品实现很方便,无须修改已有系统,符合“开闭原则”;
缺点
- 产品族扩展非常困难。在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品将涉及到对抽象工厂角色及其所有子类的修改,严重违反了开闭原则。
应用
- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
- 系统中有多于一个的产品族,而每次只使用其中某一产品族。
- 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
- 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
实现
这里我们以上面提到的CPU显卡为例子
首先定义一个工厂接口
public interface Factory {
Cpu createCpu();
Graphics createGraphics();
}
定义CPU显卡产品族:
public interface Cpu {
String workOnMainboard();
}
public interface Graphics {
String renderGraphics();
}
定义两个产品族的具体实现:
CPU族
public class AmdCpu implements Cpu {
@Override
public String workOnMainboard() {
return "AMD 3900正在主板上工作";
}
}
public class IntelCpu implements Cpu {
@Override
public String workOnMainboard() {
return "INTEL 10900正在主板上工作";
}
}
显卡族
public class AmdGraphics implements Graphics {
@Override
public String renderGraphics() {
return "AMD显卡为你渲染4K";
}
}
public class IntelGraphics implements Graphics {
@Override
public String renderGraphics() {
return "辣鸡Intel显卡为你渲染4K";
}
}
定义实现工厂的两个厂家英特尔与AMD:
public class AmdFactory implements Factory {
@Override
public Cpu createCpu() {
return new AmdCpu();
}
@Override
public Graphics createGraphics() {
return new AmdGraphics();
}
}
public class IntelFactory implements Factory {
@Override
public Cpu createCpu() {
return new IntelCpu();
}
@Override
public Graphics createGraphics() {
return new IntelGraphics();
}
}
客户端调用:
public class Client {
public static void main(String[] args) {
Factory intelFactory = new IntelFactory();
Factory amdFactory=new AmdFactory();
intelFactory.createCpu().workOnMainboard();
amdFactory.createCpu().workOnMainboard();
intelFactory.createGraphics().renderGraphics();
amdFactory.createGraphics().renderGraphics();
}
}