工厂模式的应用场景很多,到底再那些地方用过呢?为什么需要使用?有什么好处?本文将从应用场景出发逐步揭开工厂模式背后的面纱。
先对工厂模式做一个大概的说明,其定义:
Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。)
有了一个大概的概念后,我们来列举一下其应用场景:
Spring获取bean的代码如下:
# 通过xml获取Bean
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-factoryMethod.xml");
DemoApplication bean = ctx.getBean(DemoApplication.class);
# 通过DI的方式注入Bean
@Autowired
DemoApplication demoApplication;
# 通过DI的方式注入Bean
@Service
DemoApplication demoApplication;
接下来我们看看ClassPathXmlApplicationContext是怎么实现的,先看到下面的类结构图:
BeanFactory接口存在四种工厂SimpleJndiBeanFactory、HierachicalBeanFacory、AutowireCapleBeanFactory、ListableBeanFactory,这四个工厂也对应了获取Bean的不同方式比如通过Jndi获取bean就使用SimpleJndiBeanFactory工厂,通过xml获取bean就通过HierachicalBeanFacory工厂下的实现,通过依赖注入的方式就通过AutowireCapleBeanFactory工厂。
Spring中有一个最大的功能就是DI(依赖注入),所依赖的对象一般都是接口,这也吻合了设计原则中的依赖倒置原则(DIP),而创建bean与之相关的也都交给了Spring容器来管理,也就是不需要关注bean的创建过程以及与之相关的其他对象,也就是设计原则中的迪米特法则(LOD),在这里我们所有的接口也可以使用其子类来进行替换,这也就吻合里氏替换原则(LSP)。
Spring创建bean的使用的设计模式即为抽象工厂模式,需要实现不同创建bean方式只需要继承BeanFactory接口进行实现。
抽象工厂定义:
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
在最早学习Java的时候,JDBC获取数据库连接,实现代码如下:
import java.sql.Connection;
import java.sql.SQLException;
public class ConnectionFactory {
public static Connection getConnection() {
Connection conn = null;
try {
conn = DataSourceHolder.getInstance().getDataSource()
.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
}
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
public class DataSourceHolder {
private BasicDataSource ds = new BasicDataSource();
private DataSourceHolder() {
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/dbo");//dbo为连接的数据库名称
ds.setUsername("root");//账号
ds.setPassword("root");//密码
}
private static class SingletonHolder{
private static DataSourceHolder instance = new DataSourceHolder();
}
public static DataSourceHolder getInstance(){
return SingletonHolder.instance;
}
public DataSource getDataSource(){
return ds;
}
}
由于获取数据连接需要比较多的参数设置,其过程还是相对比较复制,因此使用ConnectionFactory数据库连接的工厂,非常简单的就可以获取数据库连接对象(使用ConnectionFactory .getConnection())。
以上这种使用静态方法获取数据库连接的方式就是静态工厂模式,看到这种方式是不是可以想到我们之前实现的很多代码都非常相似,比如时间工具类、Json工具类,其实这些都归纳为静态工厂或者称之为简单工厂。
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
接下来我们看看Logger的实现原理:
获取logger的对象通常会通过以下方式获取
org.slf4j.Logger logger = LoggerFactory.getLogger("DemoApplication");
查询getLogger源码:
public final class LoggerFactory {
public static Logger getLogger(String name) {
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}
public static ILoggerFactory getILoggerFactory() {
if (INITIALIZATION_STATE == UNINITIALIZED) {
synchronized (LoggerFactory.class) {
if (INITIALIZATION_STATE == UNINITIALIZED) {
INITIALIZATION_STATE = ONGOING_INITIALIZATION;
performInitialization();
}
}
}
switch (INITIALIZATION_STATE) {
case SUCCESSFUL_INITIALIZATION:
return StaticLoggerBinder.getSingleton().getLoggerFactory();
case NOP_FALLBACK_INITIALIZATION:
return NOP_FALLBACK_FACTORY;
case FAILED_INITIALIZATION:
throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
case ONGOING_INITIALIZATION:
// support re-entrant behavior.
// See also http://jira.qos.ch/browse/SLF4J-97
return SUBST_FACTORY;
}
throw new IllegalStateException("Unreachable code");
}
}
很容易就可以判别出Logger使用了静态工厂,我们可以看到getILoggerFactory()方法,在这里根据logger不同配置参数创建了不同工厂,而这里所有的工厂都是实现了ILoggerFactory接口,因此在日志这个组件中也是用了抽象工厂,因此我们可以看出不管是Spring或者日志组件都使用了抽象工厂来增强其扩展性,这也就体现了抽象工厂最大的特性就是可扩展性强,也吻合开闭原则对扩展开发对修改关闭。
接下来我们看看这样的一段代码:
产品
public abstract class Product {
//产品类的公共方法
public void method1(){
//业务逻辑处理
}
//抽象方法
public abstract void method2();
}
public class ConcreteProduct1 extends Product {
public void method2() {
//业务逻辑处理
}
}
public class ConcreteProduct2 extends Product {
public void method2() {
//业务逻辑处理
}
}
抽象工厂
public abstract class Creator {
/*
* 创建一个产品对象,其输入参数类型可以自行设置
* 通常为String、Enum、Class等,当然也可以为空
*/
public abstract T createProduct(Class c);
}
public class ConcreteCreator extends Creator {
public T createProduct(Class c){
Product product=null;
try {
product = (Product)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
//异常处理
}
return (T)product;
}
}
场景类
public class Client {
public static void main(String[] args) {
Creator creator = new ConcreteCreator();
Product product = creator.createProduct(ConcreteProduct1.class);
/*
* 继续业务处理
*/
}
}
以上是通过产品名称创建对应的产品的过程,这也是很多资料中介绍工厂模式时所使用的示例,这也就时工厂方法模式最基本的实现。
(1)简单工厂(Simple Factory)模式,又称静态工厂方法模式(Static Factory Method Pattern),一般使用静态方法进行实现。
(2)工厂方法(Factory Method)模式,又称多态性工厂(Polymorphic Factory)模式或虚拟构造子(Virtual Constructor)模式,Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。);
(3)抽象工厂(Abstract Factory)模式,Provide an interface for creating families of related or dependent objects without specifying their concrete classes.(为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。)。
笔者的微信公众号,每天一篇好文章: