工厂模式
1、什么是工厂模式?
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
2、工厂模式特性
(1)意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
(2)主要解决:主要解决接口选择的问题。
(3)何时使用:我们明确地计划不同条件下创建不同实例时。
(4)如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
(5)关键代码:创建过程在其子类执行。
3、工厂模式的优缺点及应用场景
(1)优点:
1、一个调用者想创建一个对象,只要知道其名称就可以了。
2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
3、屏蔽产品的具体实现,调用者只关心产品的接口。
(2)缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
(3)使用场景:
1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。
(4)应用实例:
1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。 2、Hibernate 换数据库只需换方言和驱动就可以。
(5)注意事项:
作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
4、工厂模式的实现
我们一般说的工厂模式指的是工厂方法模式。而简单工厂模式(或称静态工厂模式)可认为是一种工厂方法模式实现的一个特例,是一种编程实现方法,不能认为是一种设计模式。
4.1、简单工厂模式
4.1.1、简单工厂模式优缺点以及适用场景
(1)优点
- 实现了对象创建和使用的分离(即业务逻辑和界面逻辑分离)。
- 客户端无需知道所创建的具体产品类的类名,只需知道具体产品类所对应的参数即可。
- 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
(2)缺点
- 工厂类集中了所有产品的逻辑,职责过重,一旦不能工作,整个系统都要受到影响。
- 增加系统中类的个数,增加了系统的复杂度和理解难度。
- 系统扩展困难,一旦添加新产品不得不修改工厂逻辑。
- 由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构,工厂类不能得到很好地扩展。
(3)适用环境
- 工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
- 客户端只知道传入工厂类的参数,对于如何创建对象并不关心。
4.1.2、简单工厂模式实现示例
(1)假设有产品有多种,我们需要据需创建对应的产品。我们将创建产品Product接口,并创建两个具体产品子类;之后我们创建简单工厂SimpleFactory类负责创建具体的产品;创建一个应用类Application假设其作为一个应用业务,在其中调用工厂类;假设创建SimpleFactoryTest类用于测试。
(2)代码示例如下:
Product接口及两个具体产品类A,A1:
interface Product{
public void method1();
}
class ProductA implements Product{
@Override
public void method1(){
System.out.println("ProdyctA.method 1 executed.");
}
}
class ProductA1 implements Product{
@Override
public void method1(){
System.out.println("ProdyctA1.method 1 executed.");
}
}
简单工厂SimpleFactory类:
//简单工厂模式:简单工厂模式并不是一种设计模式,只能说它是一种编程实现思想
class SimpleFactory{
public static Product createProduct(String type){
if(type.equals("0")){
return new ProductA();
}else if(type.equals("1")){
return new ProductA1();
}else{
return null;
}
}
}
应用类(可选)Application类:
class Application{
private Product createProduct(String type){
//省略其他业务处理....
return SimpleFactory.createProduct(type);
}
Product getObject(String type){
Product product = createProduct(type);
//省略其他业务处理...
return product;
}
}
测试示例:
public class SimpleFactoryTest {
public static void main(String[] args) {
Application application = new Application();
Product product = application.getObject("1");
product.method1();
}
}
输出示例:
ProdyctA.method 1 executed.
ProdyctA1.method 1 executed.
后续我们需要新增产品时,需要在SimpleFactory的创建方法中增加具体的创建产品的逻辑,在需要生产该产品时,指定该产品创建的参数即可。(只有一个实体工厂类;一个实体工厂类生产所有的产品类,工厂根据传入的参数判断具体生产哪个产品给客户。)
4.2、工厂方法模式
4.2.1、工厂方法模式的优缺点及应用场景
(1)优点
- 符合开放-关闭原则(简称开-闭原则)
- 将创建对象的逻辑与任务交给了工厂类
(2)缺点
- 每次新增产品,产品类都需要创建对应工厂类,增加了系统的开销
(3)适用场景
- 创建某些类的对象的逻辑比较复杂, 并且有很多分支条件,而且还可能增加新的条件。
- 一个类不知道它所需要的对象的类 。
- 一个类通过其子类来指定创建哪个对象。
- 需要封装创建类的对象的逻辑, 使得这些逻辑局部化。
4.2.2、工厂方法模式实现示例
(1)类似上面简单工厂模式实现的场景:假设有产品有多种,我们需要据需创建对应的产品。我们将创建产品Product接口,并创建两个具体产品子类;我们创建一个工厂方法抽象类FactoryMethod类,创建两个具体工厂分别用于创建具体产品A,A1;创建SimpleFactoryTest类用于测试。
(2)代码示例如下:
接口产品类Product及具体产品ProductA,ProductA1:
interface Product{
public void method1();
}
class ProductA implements Product {
@Override
public void method1(){
System.out.println("ProdyctA.method 1 executed.");
}
}
class ProductA1 implements Product {
@Override
public void method1(){
System.out.println("ProdyctA1.method 1 executed.");
}
}
工厂方法抽象类FactoryMethod类及具体的生成产品的工厂ConcreteProductAFactory类、ConcreteProductA1Factory类:
abstract class FactoryMethod{
//工厂方法
abstract Product createProduct();//交由子类来实现
Product getObject(){
Product product = createProduct();
//省略其他业务处理...
return product;
}
}
//具体工厂的实现
class ConcreteProductAFactory extends FactoryMethod{
@Override
Product createProduct() {
//实例化的其他过程
//...
return new ProductA();
}
}
class ConcreteProductA1Factory extends FactoryMethod{
@Override
Product createProduct() {
//实例化的其他过程
//...
return new ProductA1();
}
}
测试示例FactoryMethodTes类:
public class FactoryMethodTest {
public static void main(String[] args) {
FactoryMethod A = new ConcreteProductAFactory();
Product product = A.getObject();
product.method1();
FactoryMethod A1 = new ConcreteProductA1Factory();
Product productA1 = A1.getObject();
productA1.method1();
}
}
测试结果示例:
ProdyctA.method 1 executed.
ProdyctA1.method 1 executed.
后续我们需要新增创建其他产品时,只需要实现Product接口创建具体产品,并继承FactoryMethod抽象类实现创建该产品的具体工厂,在需要生产该产品时指定具体工厂即可。(只有一个产品接口,每一种具体产品类对应一个创建工厂类)。
5、Java JDK源码中的应用
该设计模式在JDK类的应用示例如下:具体内容可查看JDK对应类源码(仅示例,非全部)
(1)简单工厂模式:
Calendar.getInstance();
java.text.NumberFormat.getInstance();
java.util.ResourceBundle.getInstance();
(2)工厂方法模式:
java.net.URLStreamHandlerFactory
java.xml.bind.JAXBContext.createMarshaller
本文源代码:
https://github.com/JianfuYang/2020-yjf-review/tree/master/src/designpatterns/factorymethod
https://github.com/JianfuYang/2020-yjf-review/tree/master/src/designpatterns/simplefactory
声明:本文部分内容整理来源于网络,仅做个人学习使用!侵删~
本文部分内容参考链接:
https://www.runoob.com/design-pattern/factory-pattern.html
https://blog.csdn.net/qq_36445854/article/details/88743994?