设计模式(2):简单工厂模式及工厂方法模式

工厂模式

1、什么是工厂模式?

2、工厂模式特性

3、工厂模式的优缺点及应用场景

4、工厂模式的实现

4.1、简单工厂模式

4.1.1、简单工厂模式优缺点以及适用场景

4.1.2、简单工厂模式实现示例

4.2、工厂方法模式

4.2.1、工厂方法模式的优缺点及应用场景

4.2.2、工厂方法模式实现示例

5、Java JDK源码中的应用


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)优点

  1. 实现了对象创建和使用的分离(即业务逻辑和界面逻辑分离)。
  2. 客户端无需知道所创建的具体产品类的类名,只需知道具体产品类所对应的参数即可。
  3. 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

(2)缺点

  1. 工厂类集中了所有产品的逻辑,职责过重,一旦不能工作,整个系统都要受到影响。
  2. 增加系统中类的个数,增加了系统的复杂度和理解难度。
  3. 系统扩展困难,一旦添加新产品不得不修改工厂逻辑。
  4. 由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构,工厂类不能得到很好地扩展。

(3)适用环境

  1. 工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
  2. 客户端只知道传入工厂类的参数,对于如何创建对象并不关心。

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)优点

  1. 符合开放-关闭原则(简称开-闭原则)
  2. 将创建对象的逻辑与任务交给了工厂类

(2)缺点

  1. 每次新增产品,产品类都需要创建对应工厂类,增加了系统的开销

(3)适用场景

  1. 创建某些类的对象的逻辑比较复杂, 并且有很多分支条件,而且还可能增加新的条件。
  2. 一个类不知道它所需要的对象的类 。
  3. 一个类通过其子类来指定创建哪个对象。
  4. 需要封装创建类的对象的逻辑, 使得这些逻辑局部化。

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?

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值