为什么要有抽象工厂
- 如果在上一篇工厂方法的介绍中多了,要把源码加进去,那么必须新增源码的抽象类,几个具体的实现类,对应的工厂抽象类,对应的具体工厂实现类。类一下子多到爆炸。而我们前面强调了,Java源码和Python源码属于同一产品等级,而源码和视频属于同一产品族。解决前者用工厂方法,解决后者用抽象工厂。
抽象工厂案例
1. 类图

2. 代码
package com.joncy.abstractFactory;
public abstract class Code {
public abstract void produce();
}
package com.joncy.abstractFactory;
public class PythonCode extends Code{
@Override
public void produce() {
System.out.println("prthon-code");
}
}
package com.joncy.abstractFactory;
public class JavaCode extends Code{
@Override
public void produce() {
System.out.println("java-code");
}
}
package com.joncy.abstractFactory;
public abstract class Video {
public abstract void produce();
}
package com.joncy.abstractFactory;
public class PythonVideo extends Video{
@Override
public void produce() {
System.out.println("python-video");
}
}
package com.joncy.abstractFactory;
public class JavaVideo extends Video{
@Override
public void produce() {
System.out.println("java-video");
}
}
package com.joncy.abstractFactory;
public interface CourseFactory {
Video getVideo();
Code getCode();
}
package com.joncy.abstractFactory;
public class PythonCourseFactory implements CourseFactory{
@Override
public Video getVideo() {
return new PythonVideo();
}
@Override
public Code getCode() {
return new JavaCode();
}
}
package com.joncy.abstractFactory;
public class JavaCourseFactory implements CourseFactory{
@Override
public Video getVideo() {
return new JavaVideo();
}
@Override
public Code getCode() {
return new JavaCode();
}
}
package com.joncy.abstractFactory;
public class Application {
public static void main(String[] args) {
CourseFactory courseFactory = new JavaCourseFactory();
Video javaVideo = courseFactory.getVideo();
Code javaCode = courseFactory.getCode();
javaVideo.produce();
javaCode.produce();
}
}
概念 & 原理
1. 定义
- 抽象工厂模式提供了一个创建**一系列相关(产品族和产品等级)**或相互依赖对象的接口。
- 类型:创建型
- 无须指定他们具体的类:将一组具有同一主题的单独的工厂封装起来,在正常使用中,客户端程序需要创建工厂的具体实现,然后使用抽象接口来创建这一主题的对象,我们在使用的时候,是不需要关心它从这些内部方法中获取对象的具体过程。抽象工厂将一组对象的实现细节和它们的使用分离开来。
2.适用场景
- 客户端(应用层)不依赖于产品类实例如何被创建、实现的细节。
- 强调一系列相关的产品对象(同属同一产品族)一起使用创建对象需要大量的重复代码
- 提供了一个产品类的库,所有产品以同样的接口出现,从而使客户端不依赖于具体实现
3. 优缺点
- 优点:
- 具体的产品在应用层代码隔离(所有的工厂都具有),无须关心创建细节。应用层代码不和具体的产品发生依赖,它只和具体的产品族工厂发生依赖关系。
- 将一个系列的产品统一到一起创建。从具体的产品族工厂取出来的肯定属于同一产品族
- 扩展性好,新增算法产品族,只需增加算法的工厂,和对应的产品类,符合开闭原则
- 缺点:
- 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口,需要进行大的修改,违背了开闭原则。所以要找相对固定的(时间很久才会改一次)。
- 增加了系统的抽象性和理解难度
4. 产品等级 & 产品族

5. 抽象工厂 or 工厂方法?
- 当一个工厂可以创建出分属于不同产品等级结构的一个产品族的对象时,抽象工厂更具效率,因为类的个数变少了
- 两者类数对比,可以发现只是多了一个产品等级,原来的工厂中单一产品等级变成了多个。

6. 重要总结
- 从应用层代码就可以看出,它根本不关心什么视频还是代码之类的,它只关心从哪个工厂里面拿到对应的产品。 从java课程里面拿视频,拿源码,肯定不会拿错。应用层即使和具体的实现类不再一个包中,也不需要导入对应实现类的包,依赖关系很少。