( 六 )、 设计模式 之 工厂方法模式(FactoryMethod)
( 六 )、 设计模式 之 工厂方法模式(FactoryMethod)
1、简介
在《简单工厂模式》一节我们介绍了简单工厂模式,提到了简单工厂模式违背了开闭原则,而“工厂方法模式”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
工厂方法模式的定义:
在抽象类中定义一个用于创建对象的抽象方法,让子类决定实例化细节, FactoryMethod 使一个类的实例化延迟到子类。工厂方法模式简称为工厂模式。
工厂方法模式的功能:
工厂方法模式的主要功能是让父类在不知道具体实现的情况下,完成自身的功能调用。而具体的实现延迟到子类来实现。这样在设计的时候,不用去考虑具体的实现,需要某个对象,把它通过工厂方法返回就好了, 在使用这些对象实现功能的时候还是通过接口来操作,这类似于IOC/DI的思想。
2、工厂方法模式结构说明:
工厂方法的实现中,通常父类会是一个①抽象类,里面包含创建所需对象的抽象方法, 这些抽象方法就是工厂方法。父类里面,通常会有使用这些产品对象来实现一定的功能的方法,
而且这些方法所实现的功能通常都是公共的功能,不管子类选择了何种具体的产品实现,这些方法的功能总是能正确执行。所以工厂方法一般是在父类(即抽象类)中被调用。
也可以把父类实现成为一个②具体的类。这种情况下,通常是在父类中提供获取所需对象的默认实现方法,这样即使没有具体的子类,也能够运行。
通常这种情况还是需要具体的子类来决定具体要如何创建父类所需要的对象。也把这种情况称为工厂方法为子类提供了挂钩。通过工厂方法,可以让子类对象来覆盖父类的实现,从而提供更好的灵活性。一般工厂方法返回的是被创建对象的接口对象,当然也可以是抽象类或者一个具体的类的实例。
工厂方法模式由抽象工厂、具体工厂、抽象产品和具体产品等4个要素构成。工厂方法模式的主要角色如下:
- 抽象产品(Product): 定义工厂方法所创建的对象的接口,也就是实际需要使用的对象的接口。
- 具体产品(ConcreteProduct): 具体的 Product 接口的实现对象。
- 抽象工厂(abstractFactory): 抽象工厂,声明工厂方法,工厂方法通常会返回一个 Product 类型的实例对象,而且多是抽象方法。也可以在 abstractFactory 里面提供工厂方法的默认实现,
让工厂方法返回一个缺省的Product类型的实例对象。 - 具体工厂(ConcreteFactory): 具体的创建器对象,覆盖实现 abstractFactory定义的工厂方法,返回具体的 Product 实例。
其结构图 如图所示:
3、代码示例
/**
* @Author dw
* @ClassName Product
* @Description 工厂方法创建对象的接口
* @Date 2023/8/18 9:22
* @Version 1.0
*/
public interface Product {
// 可以定义Product的属性和方法
}
/**
* @Author dw
* @ClassName ConcreatProduct
* @Description 具体的Product产品
* @Date 2023/8/18 9:24
* @Version 1.0
*/
public class ConcreteProduct implements Product{
// 实现Product要求的方法
}
/**
* @Author dw
* @ClassName AbstractFactory
* @Description 抽象地创建器,声明工厂方法(抽象变化,封装公共实现)
* @Date 2023/8/18 9:28
* @Version 1.0
*/
public abstract class AbstractFactory {
/**
* 创建Product的工厂方法,一般都在本类中被调用
* @return Product
*/
protected abstract Product factoryMethod ();
/**
* 示意方法,实现某些功能的具体实现逻辑。提供给子类调用
*/
public void someOperation () {
// 通常会调用工厂方法获取工厂创建的具体的对象
Product product = factoryMethod();
// 做一些通用的操作
}
}
/**
* @Author dw
* @ClassName ConcreteAbstractFactory
* @Description 工厂方法的具体实现
* @Date 2023/8/18 9:40
* @Version 1.0
*/
public class ConcreteAbstractFactory extends AbstractFactory {
/**
* 创建Product的具体方法
*
* @return Product
*/
@Override
protected Product factoryMethod() {
// 返回具体的Product
return new ConcreteProduct();
}
}
4、应用场景:
- 如果一个类需要创建某个接口的对象,但是又不知道具体的实现,这种情况可以选用工厂方法模式,把创建对象的工作延迟到子类中去实现。
- 如果一个类本身就希望由它的子类来创建所需的对象的时候,应该使用工厂方法模式。
5、优缺点
优点:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
- 灵活性增强,对于新产品的创建,只需多写一个相应的工厂实现类。
- 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
- 工厂方法模式可以将客户端与具体类的创建过程分离,使得客户端无需关注对象的创建细节,更无需知道具体产品类的类名,客户端可以更加专注于自身的业务逻辑。
- 工厂方法模式通过多态性,使得工厂方法可以创建不同的具体产品对象,提高了系统的灵活性。
缺点:
- 抽象产品只能生产一种产品(一个产品对应一个工厂),此弊端可使用 抽象工厂模式 解决。
6、与简单工厂模式的区别
简单工厂模式: 通常只在产品或对象创建逻辑很简单的情况下应用。它很容易违反高内聚低耦合原则,尤其是在产品或对象创建逻辑复杂的情况下。
工厂方法模式: 核心是一个抽象工厂类。在这个模式中,“工厂”创建的是还没有分化好的对象,其中没有逻辑判断。工厂方法模式让子类去决定具体实例化的对象,把简单的内部逻辑判断
移到了客户端代码。当系统需要加入一个新的产品时,只需要向系统中加入一个这个产品类以及它所对应的工厂类,而没有必要修改客户端,也没有必要修改抽象工厂角色或者其他也有的
具体工厂角色,在设计上完全符合设计模式的六大设计原则中的开闭原则。因此,工厂方法模式对于业务变化比较大的场景是适用的。
7、工厂方法模式在Spring、Mybatis中的应用
1、BeanFactory:Spring的BeanFactory类就是一个工厂模式的实现,它用于创建并管理Java对象。BeanFactory是一个接口,Spring框架中实现了这个接口的类有很多,
例如ListableBeanFactory、HierarchicalBeanFactory和AutowireCapableBeanFactory等。
2、 ProxyFactory:ProxyFactory是Spring框架中用于创建代理对象的工厂,它可以通过AOP将程序的行为分成不同的方面,提高程序的模块化和可维护性。
3、 SqlSessionFactory:用于创建Java中MyBatis框架的SqlSession对象的工厂,通过SqlSessionFactory可以获取SqlSession对象,进而执行数据库操作。
4、 DataSource:DataSource是用于获取数据库连接的工厂,它可以通过JNDI或者Spring配置文件中的bean定义来获取数据源对象,进而获取数据库连接。