1. 工厂方法模式(Factory Method Pattern)
Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.(定义一个用于创建对象的接口, 让子类决定实例化哪个类. 工厂方法模式使一个类的实例化延迟到子类)
1.1 工厂方法模式核心思想
工厂模式是一个典型的解耦框架, 用于解耦产品的创建。高层模块儿只需要与产品的抽象类打交道即可, 无须知道产品实现类.
1.2 工厂方法模式类图
笔者认为, 工厂方法模式类图应该添加一条线: Creator 接口依赖Product 接口
- Product: 产品的抽象类或抽象接口
- ConcreteProduct: 产品的实现类
- Creator: 抽象工厂, 定义产品的抽象创建方法
- ConcreateCreator: 具体创建工厂, 创建具体的产品.
1.3 工厂方法模式优点
- 优点:
- 扩展性强: 新增产品类时, 只需要新增工厂方法即可
- 屏蔽产品类: 调用者只需要关注产品的抽象类即可,无须关系产品实现类. 隐藏了产品实现细节
- 可维护性强:当需求变化时,可直接替换工厂实现类.
- 缺点:
- 新增一种产品时, 需要新增一个工厂类, 系统中类会增加.
- 调试较复杂, 在深度解耦设计中,只有在运行时才知道真实的对象类型是什么
1.4 适用场景
- 需要灵活的,可扩展,松耦合的框架时
- 工厂方法模式在spring框架中,也广泛的使用.
- 工厂方法模式应用非常广泛,而且有很多扩展模式.
2. 工厂方法模式
我们来设定这样一种场景, 要求使用jdbc 开发的应用,可同时在oracle 数据库和mysql等数据库环境中运行。 我们知道,对于oracle和mysql的一些sql写法是不同的,比如说分页查询. 对此我们便可以借助于标准工厂方法模式进行松耦合设计.
2.1 工厂方法模式类图
- IBaseDao: 接口, 定义数据库基本操作的抽象方法
- OracleBaseDao/MysqlBaseDao: 数据库基本操作实现类,分别对应于oracle数据库和mysql数据库的操作
- IBaseDaoFactory: 接口, 定义IBaseDao 的抽象创建方法
- OracleBaseFactory/MysqlBaseFactory: 分别用于创建 OracleBaseDao和MysqlBaseDao实例
[外链图片转存失败(img-3KxWHtI8-1566894742857)(https://raw.githubusercontent.com/zongf0504/blog-images/master/images/design-parttern/ldp-factorymethod-02.png)]
2.2 抽象产品类-IBaseDao
定义数据库基本基本操作的抽象方法
public interface IBaseDao {
void save();
}
2.2 mysql实现类-MysqlBaseDao
提供mysql 数据库基本操作实现类
public class MysqlBaseDao implements IBaseDao {
@Override
public void save() {
System.out.println("mysql 执行save操作...");
}
}
2.3 oracle类-OracleBaseDao
提供oracle 数据库基本操作实现类
public class OracleBaseDao implements IBaseDao {
@Override
public void save() {
System.out.println("oracle 执行save操作...");
}
}
2.4 抽象工厂类-IBaseDaoFactory
定义获取BaseDao 的抽象工厂
public interface IBaseDaoFactory {
IBaseDao getBaseDao();
}
2.5 mysql实现工厂-MysqlDaoFactory
public class MysqlDaoFactory implements IBaseDaoFactory {
@Override
public IBaseDao getBaseDao() {
return new MysqlBaseDao();
}
}
2.6 oracle实现工厂-OracleDaoFactory
public class OracleDaoFactory implements IBaseDaoFactory {
@Override
public IBaseDao getBaseDao() {
return new OracleBaseDao();
}
}
2.7 测试类
当切换数据库时,只需要修改工厂实例的创建一处地方即可:
- 当使用OracleDaoFactory 创建baseDaoFactory 实例时, 便使用OracleBaseDao 对象操作oracle 数据库
- 当使用MysqlDaoFactory 创建baseDaoFactory 实例时, 便使用MysqlBaseDao 对象操作mysql 数据库
// 使用oracle 数据库时,创建OracleDaoFactory
@Test
public void test_mysql(){
IBaseDaoFactory baseDaoFactory = new OracleDaoFactory();
IBaseDao baseDao = baseDaoFactory.getBaseDao();
baseDao.save();
}
// 使用mysql 数据库时,创建MysqlDaoFactory
@Test
public void test_oracle(){
IBaseDaoFactory baseDaoFactory = new MysqlDaoFactory();
IBaseDao baseDao = baseDaoFactory.getBaseDao();
baseDao.save();
}
3. 工厂方法模式扩展-静态工厂方法模式
- 静态方法模式, 也称简单方法模式, 是工厂方法模式的一种扩展模式。
- 简单工厂方式就是移除了抽象工厂接口, 将获取对象的方法修改为static.
3.1 静态工厂方法模式优缺点
- 优点: 调用简单, 直接通过类名调用即可
- 扩展性较差: 主要体现在Factory的扩展性差,当我们能明确抽象工厂只有一种实现时, 便可以采用静态工厂方法模式。
3.2 静态工厂类
当不考虑扩展性时, 静态工厂方法模式完全可以不依赖于IBaseDao,与OracleBaseDao和MysqlBaseDao 直接打交道
public class BaseDaoFactory {
public static IBaseDao getOracleBaseDao() {
return new OracleBaseDao();
}
public static IBaseDao getMysqlBaseDao() {
return new MysqlBaseDao();
}
}
3.3 测试
@Test
public void test_static(){
IBaseDao baseDao;
// 使用mysql
baseDao = BaseDaoFactory.getMysqlBaseDao();
baseDao.save();
// 使用oracle
baseDao = BaseDaoFactory.getOracleBaseDao();
baseDao.save();
}