工厂模式,与单例模式一样,属于创建型模式,而工厂模式还可以细分为:
(1)简单工厂模式,或者称之为静态工厂模式
(2)工厂方法模式
(3)抽象工厂模式
一、简单工厂模式
既然工厂模式的目的是为了创建对象,首先得有要有待创建的对象,假如要生产一辆汽车,定义如下:
public abstract class Car {
public abstract void run();
}
这是一个抽象类,假如有两个实现类:
public class BWM extends Car{
@Override
public void run() {
System.out.println("宝马汽车在跑");
}
}
public class BYD extends Car{
@Override
public void run() {
System.out.println("比亚迪汽车在跑");
}
}
现在需要根据用户的需求返回不同是实例对象,创建一个工厂类:
public class SimpleFactory {
public static Car getCar(String type){
if ("BWM".equals(type)){
return new BWM();
}else if ("BYD".equals(type)){
return new BYD();
}else {
System.out.println("输入的类型不正确");
return null;
}
}
}
简单工厂的核心,就是这个工厂类了,实质就是,它根据传入的不同类型,返回不同的对象,由于返回对象的方法,一般都做成静态方法,所有又称之为,静态工厂。在使用时,只需要传入要创建的对象类型即可:
public class TestSimpleFactory {
public static void main(String[] args) {
Car car = SimpleFactory.getCar("BWM");
car.run();
}
}
二、工厂方法模式
工厂方法模式,与简单工厂相比,不同的是,对工厂进一步抽象,由具体的实例工厂创建对象
抽象工厂定义,返回汽车对象:
public interface CarFactory {
Car getCar();
}
然后,由具体的工厂子类来实例化对象:
public class BWMFactory implements CarFactory{
@Override
public Car getCar() {
return new BWM();
}
}
public class BYDFactory implements CarFactory{
@Override
public Car getCar() {
return new BYD();
}
}
使用也很简单,需要什么类型的汽车,就new一个对应的工厂,再由工厂方法对象即可:
public class TestFactoryMethod {
public static void main(String[] args) {
BWMFactory factory = new BWMFactory();
Car car = factory.getCar();
car.run();
}
}
三、抽象工厂模式
抽象工厂模式,与工厂方法模式的区别在于,抽象工厂可以返回多个不同类型的产品,而工厂方法只返回一种类型的产品,如果抽象工厂只返回一种类型的产品,则抽象工厂模式就退化为工厂方法模式。
抽象工厂返回多个类型的产品:
// 抽象工厂
public interface CarFactory {
// 获取发动机
CarEngine getCarEngine();
// 获取方向盘
CarWheel getCarWheel();
}
具体工厂:
public class BWMFactory implements CarFactory {
@Override
public CarEngine getCarEngine() {
return new BWMEngine();
}
@Override
public CarWheel getCarWheel() {
return new BWMWheel();
}
}
public class BYDFactory implements CarFactory {
@Override
public CarEngine getCarEngine() {
return new BYDEngine();
}
@Override
public CarWheel getCarWheel() {
return new BYDWheel();
}
}
CarEngine和CarWheel都是产品的抽象类,这样,工程类就可以返回多个不同类型的产品了
public class TestAbsFactory {
public static void main(String[] args) {
CarFactory bwmFactory = new BWMFactory();
CarEngine carEngine = bwmFactory.getCarEngine();
CarWheel carWheel = bwmFactory.getCarWheel();
carEngine.engine();
carWheel.wheel();
System.out.println("====分割线====");
CarFactory bydFactory = new BYDFactory();
CarEngine carEngine2 = bydFactory.getCarEngine();
CarWheel carWheel2 = bydFactory.getCarWheel();
carEngine2.engine();
carWheel2.wheel();
}
}
四、应用实例
相信大家都用过mybatis,对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();
}
这个接口,别看写了那么多方法,其实就做了两件事,返回SqlSession和Configuration对象,实现类有两个:
SqlSessionManager,我没有用过,一般都是用DefaultSqlSessionFactory,看看如何返回SqlSession的:
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); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
注意到,它是直接new了一个DefaultSqlSession,因为SqlSessionManager并没有用到,不用判断使用哪个
return new DefaultSqlSession(configuration, executor, autoCommit);
再看DataSourceFactory获取数据源的工厂,也使用了工厂模式:
public interface DataSourceFactory {
void setProperties(Properties props);
DataSource getDataSource();
}
它有3个工厂子类:
Jndi用得比较少,我们看下UnpooledDataSourceFactory和PooledDataSourceFactory
UnpooledDataSourceFactory在构造方法直接new了一个UnpooledDataSource
public UnpooledDataSourceFactory() {
this.dataSource = new UnpooledDataSource();
}
而PooledDataSourceFactory继承于UnpooledDataSourceFactory,将返回的数据源变成PooledDataSource
public PooledDataSourceFactory() {
this.dataSource = new PooledDataSource();
}