抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。
在抽象工厂模式中,每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品。
在抽象工厂模式包含如下几个角色:
在抽象工厂中声明了多个工厂方法,用于创建不同类型的产品,抽象工厂可以是接口,也可以是抽象类或者具体类
具体工厂实现了抽象工厂,每一个具体的工厂方法可以返回一个特定的产品对象,而同一个具体工厂所创建的产品对象构成了一个产品族
抽象工厂模式的主要优点如下:
抽象工厂模式的主要缺点如下:
适用场景:
首先定义我们的抽象产品 Article
和 Video
,他们是产品族的抽象类,有一个 Article
就有一个 Video
public abstract class Article {
public abstract void produce();
}
public abstract class Video {
public abstract void produce();
}
具体产品 JavaArticle
、PythonArticle
、PythonVideo
、JavaVideo
public class JavaArticle extends Article {
@Override
public void produce() {
System.out.println("编写Java课程笔记记");
}
}
public class PythonArticle extends Article {
@Override
public void produce() {
System.out.println("编写Python课程笔记");
}
}
public class JavaVideo extends Video {
@Override
public void produce() {
System.out.println("录制Java课程视频");
}
}
public class PythonVideo extends Video {
@Override
public void produce() {
System.out.println("录制Python课程视频");
}
}
定义我们的抽象工厂 CourseFactory
,与工厂方法模式不同,工厂方法模式中一个工厂只生产一个产品,而抽象工厂模式中一个工厂生产一族产品,有多个工厂方法
public interface CourseFactory {
Video getVideo();
Article getArticle();
}
具体工厂 JavaCourseFactory
和 PythonCourseFactory
,它们都继承抽象工厂接口 CourseFactory
public class JavaCourseFactory implements CourseFactory {
@Override
public Video getVideo() {
return new JavaVideo();
}
@Override
public Article getArticle() {
return new JavaArticle();
}
}
public class PythonCourseFactory implements CourseFactory {
@Override
public Video getVideo() {
return new PythonVideo();
}
@Override
public Article getArticle() {
return new PythonArticle();
}
}
客户端只需要指定具体工厂,就可以获取该工厂生产的一族产品
public class Test {
public static void main(String[] args) {
CourseFactory courseFactory = new JavaCourseFactory();
Video video = courseFactory.getVideo();
Article article = courseFactory.getArticle();
video.produce();
article.produce();
}
}
输出
录制Java课程视频
编写Java课程笔记
也可以利用反射机制和配置文件,当需要修改具体工厂的时候就不需要修改客户端代码,只改配置文件即可
public class Test {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
// 从配置文件或数据库等外部渠道获取具体工厂类名
String factoryName = "com.designpattern.JavaCourseFactory";
// 通过反射机制获取工厂类
Class c = Class.forName(factoryName);
CourseFactory courseFactory = (CourseFactory) c.newInstance();
Video video = courseFactory.getVideo();
Article article = courseFactory.getArticle();
video.produce();
article.produce();
}
}
最终的类图如下所示
示例.抽象工厂类图
我们来看 java.sql
包下的 Connection
接口,该接口定义了与特定数据库的连接 Connection
,执行 SQL statements
并返回 results
public interface Connection extends Wrapper, AutoCloseable {
Statement createStatement() throws SQLException;
PreparedStatement prepareStatement(String sql) throws SQLException;
CallableStatement prepareCall(String sql) throws SQLException;
DatabaseMetaData getMetaData() throws SQLException;
Savepoint setSavepoint() throws SQLException;
Clob createClob() throws SQLException;
Blob createBlob() throws SQLException;
SQLXML createSQLXML() throws SQLException;
// ...省略...
}
其中 Statement
、PreparedStatement
、CallableStatement
、DatabaseMetaData
、Savepoint
、Clob
、Blob
、SQLXML
等均为接口
我们来看 Statement
接口
public interface Statement extends Wrapper, AutoCloseable {
ResultSet executeQuery(String sql) throws SQLException;
int executeUpdate(String sql) throws SQLException;
void close() throws SQLException;
int getMaxFieldSize() throws SQLException;
boolean execute(String sql) throws SQLException;
// ...省略...
}
其中的 ResultSet
又是一个接口
public interface ResultSet extends Wrapper, AutoCloseable {
boolean next() throws SQLException;
void close() throws SQLException;
boolean wasNull() throws SQLException;
String getString(int columnIndex) throws SQLException;
//...省略...
}
我们可以看一下他们的实现类
Connection的实现类
Statement的实现类
ResultSet的实现类
可以看出这里边的抽象工厂模式,Connection
为抽象工厂,工厂方法很多,其中一个抽象产品为 Statement
,同时 Statement
也是一个抽象工厂,工厂方法也很多,其中一个抽象产品为 ResultSet
,具体工厂和具体产品则为他们的实现类
参考: 刘伟:设计模式Java版 慕课网java设计模式精讲 Debug 方式+内存分析