定义:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法把实例化推迟到子类。
用户只需要关心生产相应对象的工厂(符合单一职能原则)每个产品由相对应的工厂生产,无需关心创建细节,而且加入新的产品符合开闭原则。
来个类图
工厂方法模式示例代码
//抽象的产品接口
public interface ICourse {
public void record();
}
public class JavaCourse implements ICourse {
@Override
public void record() {
System.out.println(" 我是Java课程 ");
}
}
public class PythonCourse implements ICourse {
@Override
public void record() {
System.out.println(" 我是Python课程 ");
}
}
//抽象工厂只有生产共同抽象接口的产品
public interface ICourseFactory {
public ICourse create();
}
public class JavaCourseFactory implements ICourseFactory{
@Override
public ICourse create() {
return new JavaCourse();
}
}
public class PythonFactory implements ICourseFactory {
@Override
public ICourse create() {
return new PythonCourse();
}
}
工厂方法模式的UML:
工厂方法模式适用场景:
- 创建对象需要大量重复代码
- 客户端(应用层)不依赖于产品类实例如何被创建,实现等细节
- 一个类通过其子类来指定创建那个对象
缺点:
- 类的个数多,增加复杂度
- 增加了系统的抽象性和理解难度
框架中的应用
- logback 中工厂方法模式的应用
抽象工厂定义:提供一个接口,将一系列的产品族统一到一起创建,而不需要明确指定具体类。有时候我们希望一个工厂可以提供多个产品对象。
先理解两个概念
- 产品族:是指由同一个工厂生产的,位于不同产品等级结构中的一组产品
- 产品等级:产品等级结构即产品的继承结构
还用上篇文章工厂方法模式中例子,现在不仅要录视频还要手记,如Java手记、Python手记等,要是按照工厂模式,需要创建Java手记类、python手记类、Java手记工厂、python 手记工厂、手记工厂类,很容易发生类爆炸情况。其中Java视频、python 视频是一个产品等级都是视频,Java手记、python手记又是一个产品等级,Java视频和Java手记是同一产品族
示例代码
//抽象的视频产品
public abstract class Video {
public abstract void produce();
}
public abstract class Article {
public abstract void produce();
}
public class JavaVideo extends Video {
@Override
public void produce() {
System.out.println("我是Java视频");
}
}
public class JavaArticle extends Article {
@Override
public void produce() {
System.out.println("我是Java文章");
}
}
public class PythonVideo extends Video {
@Override
public void produce() {
System.out.println("我是python视频");
}
}
public class PythonArticle extends Article {
@Override
public void produce() {
System.out.println("我是PythonArticle文章");
}
}
//定义工厂
public interface CourseFactory {
public Article getArticle();
public Video getVideo();
}
public class JavaFactory implements CourseFactory{
@Override
public Article getArticle() {
return new JavaArticle();
}
@Override
public Video getVideo() {
return new JavaVideo();
}
}
public class PythonFactory implements CourseFactory{
@Override
public Article getArticle() {
return new PythonArticle();
}
@Override
public Video getVideo() {
return new PythonVideo();
}
}
//测试
public class AbstractFactoryTest {
public static void main(String[] args) {
CourseFactory javaFactory = new JavaFactory();
CourseFactory pythonFactory = new PythonFactory();
javaFactory.getVideo();
pythonFactory.getArticle();
}
}
在来一个升级版抽象工厂的类图
抽象工厂模式UML
是时候总结一把了:工厂方法用继承创建对象,而抽象工厂通过对象的组合来创建。抽象工厂完美利用了依赖倒置原则,指导我们避免依赖具体类型
当系统所提供的工厂生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构、属于不同类型的具体产品时就可以使用抽象工厂模式。抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形式。抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、更有效率
几个指导方针
- 变量不可以持有具体类的引用
- 不要让类派生具体类
- 不要覆盖基类中实现的方法