一、工厂模式
一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
- 主要解决:主要解决接口选择的问题。
- 何时使用:我们明确地计划不同条件下创建不同实例时。
1.1 简单工厂模式
使用静态工厂方法,给过判定传入参数的类型判断创建什么类型的对象,类图如下:

产品抽象:
1 2 3
| public interface IProduct { String getName(); }
|
具体产品:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class ProductA implements IProduct { @Override public String getName() { return "product A"; } }
public class ProductB implements IProduct { @Override public String getName() { return "product B"; } }
|
简单工厂:
1 2 3 4 5 6 7 8 9 10 11
| public class SimpleFactory { public static IProduct getProduct(String type) { if (type.equals("A")) { return new ProductA(); } else if (type.equals("B")) { return new ProductB(); } else { return null; } } }
|
使用:
1 2 3 4 5 6
| public class TestSimpleFactory { public static void main(String[] args) { System.out.println(SimpleFactory.getProduct("A").getName()); System.out.println(SimpleFactory.getProduct("B").getName()); } }
|
1.2 工厂方法模式
使静态方法,对不同的产品使用不同的工厂方法创建产品:

工厂方法:
1 2 3 4 5 6 7 8 9
| public class MethodFactory { public static IProduct getProudctA() { return new ProductA(); }
public static IProduct getProudctB() { return new ProductB(); } }
|
使用:
1 2 3 4 5 6
| public class TestMethodFactory { public static void main(String[] args) { System.out.println(MethodFactory.getProudctA().getName()); System.out.println(MethodFactory.getProudctB().getName()); } }
|
1.3 抽象工厂模式
将产品升级为二维,在产品A B的基础上创建新的特性X Y, 类图:

抽象工厂:
1 2 3 4 5
| public interface IAbstractFactory { IProduct getProductA();
IProduct getProductB(); }
|
具体工厂:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class FactoryX implements IAbstractFactory{ @Override public IProduct getProductA() { return new ProductAX(); }
@Override public IProduct getProductB() { return new ProductBX(); } }
public class FactoryY implements IAbstractFactory{ @Override public IProduct getProductA() { return new ProductAY(); }
@Override public IProduct getProductB() { return new ProductBY(); } }
|
具体产品:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public class ProductAX extends ProductA { @Override public String getName() { return super.getName() + " X"; } }
public class ProductAY extends ProductA { @Override public String getName() { return super.getName() + " Y"; } }
public class ProductBX extends ProductB { @Override public String getName() { return super.getName() + " X"; } }
public class ProductBY extends ProductB { @Override public String getName() { return super.getName() + " Y"; } }
|
使用:
1 2 3 4 5 6 7 8 9 10 11 12
| public class TestAbstractFactory { public static void main(String[] args) { IAbstractFactory factoryX = new FactoryX(); System.out.println(factoryX.getProductA().getName()); System.out.println(factoryX.getProductB().getName());
IAbstractFactory factoryY = new FactoryY(); System.out.println(factoryY.getProductA().getName()); System.out.println(factoryY.getProductB().getName());
} }
|
二、实例分析
2.1 抽象工厂案例
在mybatis中工厂模式随处可见,SqlSessionFactory就是一个典型的抽象工厂的应用,请看下图:

具体工厂类DefaultSqlSessionFactory会产生返回一个DefaultSqlSession,它是一个线程不安全的并且需要手动close的对象,当我们单独使用mybatis的时候会使用该对象,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { final Environment environment = configuration.getEnvironment(); final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); final Executor executor = configuration.newExecutor(tx, execType); return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { closeTransaction(tx); throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
|
SqlSessionManager同时继承了SqlSessionFactory和SqlSesion接口,这表示它既是工厂类又是产品类,它作为SqlSession与DefaultSqlSession最大的区别是它内部维护一个线程安全的代理类,并且代理类执行完代理方法会自动调用close方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| private class SqlSessionInterceptor implements InvocationHandler { public SqlSessionInterceptor() { }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { final SqlSession sqlSession = SqlSessionManager.this.localSqlSession.get(); if (sqlSession != null) { try { return method.invoke(sqlSession, args); } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } } else { try (SqlSession autoSqlSession = openSession()) { try { final Object result = method.invoke(autoSqlSession, args); autoSqlSession.commit(); return result; } catch (Throwable t) { autoSqlSession.rollback(); throw ExceptionUtil.unwrapThrowable(t); } } } } }
|
线程安全就是通过ThreadLocal在每个线程内部维护一个副本来实现的:
1 2 3 4 5 6 7 8 9 10
| private final ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<>();
public void startManagedSession() { this.localSqlSession.set(openSession()); }
@Override public SqlSession openSession() { return sqlSessionFactory.openSession(); }
|
2.2 简单工厂案例
在具体工厂类DefaultSqlSessionFactory的openSessionFromConnection方法会创建真正执行sql的Executor对象,该对象的创建就是通过Configuration类的newExecutor方法实现,请看下面代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Executor executor; if (ExecutorType.BATCH == executorType) { executor = new BatchExecutor(this, transaction); } else if (ExecutorType.REUSE == executorType) { executor = new ReuseExecutor(this, transaction); } else { executor = new SimpleExecutor(this, transaction); } if (cacheEnabled) { executor = new CachingExecutor(executor); } executor = (Executor) interceptorChain.pluginAll(executor); return executor; }
|