抽象工厂模式指提供一个创建一系列相关或者相互依赖对象的接口,无须指定他们具体的类,意思是客户端不必指定产品的具体类型,创建多个产品族中的产品对象。
抽象工厂模式中,客户端不依赖产品类如何被创建,实现等细节,强调一系列相关的产品对象一起创建对象,需要大量重复的代码
需要提供一个产品的类库,所有的产品以同样的接口出现,从而使客户端不依赖具体的实现
上图中有矩形,圆形和菱形3中图形,相同颜色,相同深浅的代表同一个产品族,相同形状的代表同一个产品等级。
抽象工厂模式适用于需要生成产品族的情景,抽象产品类内部提供了多个其他抽象产品,抽象工厂类定义了产品的创建接口,通过具体的工厂子类,就可以生产相应的产品族对象,供用户端使用
右上图可知,抽象工厂模式主要包含4个角色
抽象工厂:声明创建抽象产品对象的一个操作接口
具体工厂:实现创建具体产品对象的操作
抽象产品:为一类产品对象声明一个接口
具体产品:定义一个将被相应的具体工厂创建的产品对象,实现AbstractProduct接口
public class Client{
public static void main(String[] args){
IFactory factory = new ConcreateFactoryA();
factory.makeProductA();
factory.makeProductB();
factory = new ConcreateFactoryB();
factory.makeProductA();
factory.makeProductB();
}
}
//抽象工厂
public interface IFactory{
IProductA makeProductA();
IProductB makeProductB();
}
//产品A抽象
public interface IProductA{
void doA();
}
//产品B抽象
public interface IProductB{
void doB();
}
//产品族A的具体产品A
public class ConcreateProductAWithFamilyA implements IProductA{
public void doA(){
System.out.println("The ProductA be part of FamilyA")
}
}
//产品族A的具体产品B
public class ConcreateProductWBithFamilyA implements IProductB{
public void doB(){
System.out.println("The ProductB be part of FamilyA")
}
}
//产品族B的具体产品A
public class ConcreateProductAWithFamilyB implements IProductA{
public void doA(){
System.out.println("The ProductA be part of FamilyB")
}
}
//产品族B的具体产品B
public class ConcreateProductWBithFamilyB implements IProductB{
public void doB(){
System.out.println("The ProductB be part of FamilyB")
}
}
//具体工厂类A
public class ConcreateFactoryA implements IFactory{
public IProductA makeProductA(){
return new ConcreateProductAWithFamilyA();
}
public IProductB makeProductB(){
return new ConcreateProductBWithFamilyA();
}
}
//具体工厂类B
public class ConcreateFactoryB implements IFactory{
public IProductA makeProductA(){
return new ConcreateProductAWithFamilyB();
}
public IProductB makeProductB(){
return new ConcreateProductBWithFamilyB();
}
}
我们来看一个具体的业务场景,并且用代码来实现。还是以课程为例,假设每个课程要提供课程的录播视频还有课堂笔记,相当于现在的业务包括一个课程要有课程信息,录播视频,课堂笔记,甚至提供源码,首先在产品等级中增加两个产品,录播视频和课堂笔记
IVideo接口的代码如下:
public interface IVideo{
void record();
}
INote接口代码如下
public interface INote{
void note();
}
然后创建一个抽象工厂CourseFactory类:
public abstract class CourseFactory{
public void init(){
System.out.println("初始化基础数据");
}
protected abstract INote createNote();
protected abstract IVideo createVideo();
}
接下来创建Java产品族,Java视频JavaVideo类的代码如下:
public class JavaVideo implements IVideo{
public void record(){
System.out.println("录制Java视频");
}
}
扩展产品等级Java课堂笔记JavaNote类
public class JavaNote implements INote{
public void note(){
System.out.println("编写Java笔记");
}
}
创建java产品族的具体工厂JavaCourseFactory
public class JavaCourseFactory extends CourseFactory{
public INote createNote(){
super.init();
return new JavaNote();
}
public IVideo createVideo(){
super.init();
return new JavaVideo();
}
}
随后创建Python产品族,Python视频PythonVideo类的代码如下
public class PythonVideo implements IVideo{
public void record(){
System.out.println("录制python视频");
}
}
扩展产品等级Python课堂笔记PythonNote类
public class PythonNote implements INote{
public void note(){
System.out.println("编写Python笔记");
}
}
创建Python产品族的具体工厂PythonCourseFactory
public class PythonCourseFactory extends CourseFactory{
public INote createNote(){
super.init();
return new PythonNote();
}
public IVideo createVideo(){
super.init();
return new PythonVideo();
}
}
最后来看客户端调用代码
public static void main(String[] args){
JavaCourseFactory factory = new JavaCourseFactory();
factory.createNote().note();
factory.createVideo().record();
}
上面代码完整的描述了Java课程和Python课程两个产品族,抽象工厂模式非常清晰描述了这样一层的复杂关系。但是,不知道如果继续扩展产品,将Source也加入课程中,则代码从抽象工厂到具体的工厂要全部调整,这显然不符合开闭原则。
当需要产品族时,抽象工厂可以保证客户端始终只是用同一个产品的产品族
抽象工厂增强了程序的可扩展性,对于新产品族的增加,只需实现一个新的具体工厂即可,不需要对已有代码进行修改,符合开闭原则
规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
增加了系统的抽象性和理解难度