工厂模式,与单例模式一样,属于创建型模式,而工厂模式还可以细分为:
(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(); }