定义:抽象工厂模式提供一个创建一系列相关或者相互依赖对象的接口。
对比 简单工厂、工厂方法、抽象工厂
模式 | 优点 | 缺点 |
---|---|---|
简单工厂 | 将创建对象的逻辑封装在一个静态方法中,外部人员不需要关注内部实现逻辑 | 创建对象的逻辑存在一个静态方法中不方便扩展、不能被继承、违背开闭原则 |
工厂方法 | 通过提供多个工厂类来创建不同对象,解决了简单工厂模式中职责过重问题,方便扩展、可以被继承、符合开闭原则 | 对象太多的时候就会创建很多工厂类 |
抽象工厂 | 通过提供多个工厂类来创建同一产品族对象,方便扩展、可以被继承、符合开闭原则,并且减少了工厂类数量 | 实现起来比较复杂,不如简单工厂模式使用简单,产品族需要划分 |
下面通过一个例子来实现抽象工厂模式。
宝马品牌车有宝马X1、X3、X5等系列,每个系列车又配有各自的系列车标X1、X3、X5(车标只能由自己工厂创建),这三个系列车和车标分别由三个工厂创建,下面通过抽象工厂模式来实现该例子。
UML图
IBMWFactory接口定义了createCar(生产车)和createLogo(生产车标)方法,X1Factory、X3Factory、X5Factory造车工厂实现该接口,同时提供生产车型和车标的方法。
X1Car、X3Car、X5Car都实现实体BMWCar接口,并实现run方法。
创建IBMWCar接口,并定义run方法。
public interface IBMWCar {
void run();
}
创建宝马X1车类,并实现IBMWCar接口,实现run方法。
public class X1Car implements IBMWCar {
@Override
public void run() {
System.out.println("X1Car run");
}
}
创建宝马X3车类,并实现IBMWCar接口,实现run方法。
public class X3Car implements IBMWCar {
@Override
public void run() {
System.out.println("X3Car run");
}
}
创建宝马X5类,并实现IBMWCar接口,实现run方法。
public class X5Car implements IBMWCar {
@Override
public void run() {
System.out.println("X5Car run");
}
}
创建ILogo接口,并定义create方法。
public interface ILogo {
void create();
}
创建宝马X1Logo车标类,并实现ILogo接口,实现create方法。
public class X1Logo implements ILogo {
@Override
public void create() {
System.out.println("创建X1Logo");
}
}
创建宝马X3Logo车标类,并实现ILogo接口,实现create方法。
public class X3Logo implements ILogo {
@Override
public void create() {
System.out.println("创建X3Logo");
}
}
创建宝马X5Logo车标类,并实现ILogo接口,实现create方法。
public class X5Logo implements ILogo {
@Override
public void create() {
System.out.println("创建X5Logo");
}
}
创建工厂接口,定义createCar方法。
public interface IBMWFactory {
public IBMWCar createCar();
}
创建X1工厂类,并实现工厂接口,实现createCar方法,创建X1Car对象,实现createLogo方法创建X1车标对象。
public class X1Factory implements IBMWFactory {
@Override
public IBMWCar createCar() {
return new X1Car();
}
@Override
public ILogo createLogo() {
return new X1Logo();
}
}
创建X3工厂类,并实现工厂接口,实现createCar方法,创建X3Car对象,实现createLogo方法创建X3车标对象。
public class X3Factory implements IBMWFactory {
@Override
public IBMWCar createCar() {
return new X3Car();
}
@Override
public ILogo createLogo() {
return new X3Logo();
}
}
创建X5工厂类,并实现工厂接口,实现createCar方法,创建X5Car对象,实现createLogo方法创建X5车标对象。
public class X5Factory implements IBMWFactory {
@Override
public IBMWCar createCar() {
return new X5Car();
}
@Override
public ILogo createLogo() {
return new X5Logo();
}
}
public class Test {
public static void main(String[] args) {
// 创建X1工厂类,并创建X1车和X1车标
X1Factory x1Factory = new X1Factory();
IBMWCar carX1 = x1Factory.createCar();
carX1.run();
ILogo logo1 = x1Factory.createLogo();
logo1.create();
// 创建X3工厂类,并创建X3车和X3车标
X3Factory x3Factory = new X3Factory();
IBMWCar carX3 = x3Factory.createCar();
carX3.run();
ILogo logo3 = x3Factory.createLogo();
logo3.create();
// 创建X5工厂类,并创建X5车和X5车标
X5Factory x5Factory = new X5Factory();
IBMWCar carX5 = x5Factory.createCar();
carX5.run();
ILogo logo5 = x5Factory.createLogo();
logo5.create();
}
}
运行结果:
X1Car run
创建X1Logo
X3Car run
创建X3Logo
X5Car run
创建X5Logo
以上便是抽象工厂模式的原理和代码实现,相比工厂方法模式,多了车标产品,所以可以把品牌和车标统称为一系列产品族,这种场景便可以使用抽象工厂模式来实现。
示例代码:abstract_factory
Mybatis库做Java服务开发的都不陌生,在Mybatis库中创建SqlSession时就是使用了抽象工厂模式,类路径:org.apache.ibatis.session.SqlSessionFactory
public interface SqlSessionFactory {
SqlSession openSession();
SqlSession openSession(boolean autoCommit);
SqlSession openSession(Connection connection);
SqlSession openSession(TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType);
SqlSession openSession(ExecutorType execType, boolean autoCommit);
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType, Connection connection);
Configuration getConfiguration();
}
它的子类有SqlSessionManager
和SqlSessionManager
都提供了打开Session的方法和getConfiguration方法。
创建的对象是SqlSession和Configuration两个相关对象,Configuration为相关配置信息,SqlSession类路径为:org.apache.ibatis.session.SqlSession
,源码如下:
public interface SqlSession extends Closeable {
<T> T selectOne(String statement);
<T> T selectOne(String statement, Object parameter);
<E> List<E> selectList(String statement);
<E> List<E> selectList(String statement, Object parameter);
......
}
这里提供了常用的sql执行接口。SqlSession的子类有:DefaultSqlSession、SqlSessionManager、SqlSessionTemplate
,子类在创建后会提供对应的Sql执行接口。