2

Java真的不难(二十九)工厂模式(2)

 2 years ago
source link: https://blog.csdn.net/m0_57310550/article/details/123623114
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

工厂模式(2):工厂方法模式

在上一篇文章中介绍了简单工厂模式,但是简单工厂模式违背了开闭原则,而工厂方法模式是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。

一、什么是工厂方法模式?

工厂方法模式:也叫虚拟构造器模式或者多态工厂模式,它属于类创建型模式。

在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

我们知道在现在的真实工厂内分工越来越细,越来越专业化。。各种产品有专门的工厂生产,彻底告别了自给自足的小农经济时代,这大大缩短了产品的生产周期,提高了生产效率。而工厂方法模式即满足了开闭原则,也继承了简单工厂模式的优点。

举例说明:

在简单工厂模式的文章中的可乐工厂,因为只有一个工厂类,所以任何产品都需要在这个类里面去修改和调整,而工厂方法模式就是有多个工厂,每个工厂生产一个产品,如果有需要增加新产品,我们直接再新建一个工厂即可,就不需要在其他工厂的内部再去修改,这样就符合了开闭原则。

二、工厂方法模式的优缺点

优点:

  1. 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程
  2. 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类
  3. 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则

缺点:

  1. 类的个数容易过多,增加复杂度
  2. 增加了系统的抽象性和理解难度
  3. 抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决(抽象工厂模式在下一篇文章)

三、模式的结构与实现

结构由以下四个部分组成:

  1. 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品
  2. 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建
  3. 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能
  4. 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应

结构图:

在这里插入图片描述

4、工厂方法模式代码实现

还是以上一篇文章的可乐工厂为例:
产品有:可口可乐、百事可乐、无糖可乐
在简单工厂模式中只有一个可乐工厂,可以生产三种产品,在工厂方法模式中就可以有多个工厂来生成对应的产品:

抽象工厂: 可乐工厂(可以理解成总厂)
百事可乐工厂: 生成百事可乐
可口可乐工厂: 生成可口可乐
无糖可乐工厂: 生成无糖可乐

生产可乐的方法:

/**
 *  提供了产品的接口
 */

public interface Cola {

    //生产可乐的方法
    public void cola();
}

可乐抽象工厂:

/**
 * 可乐抽象工厂(可以理解成可乐总厂,旗下还有很多分厂)
 */

public interface ColaFactory {

    public Cola newCola();
}

生成三种可乐的方法:
可乐可乐:

/**
 * 产品名称:可乐可乐,实现了产品的接口
 */

public class CocaCola implements Cola{

    @Override
    public void cola() {
        System.out.println("开始生产可口可乐");
    }
}

百事可乐:

/**
 *
 * 产品名称:百事可乐,实现了产品的接口
 */

public class PepsiCola implements Cola{

    @Override
    public void cola() {
        System.out.println("开始生产百事可乐");
    }
}

无糖可乐:

/*
 * 产品名称:无糖可乐,实现了产品的接口
 */

public class SugarFreeCola implements Cola{

    @Override
    public void cola() {
        System.out.println("开始生产无糖可乐");
    }
}

三个产品对应三个工厂:

生产可口可乐的工厂:

/**
 *
 * 具体工厂1:可口可乐工厂
 */

public class CocaColaFactory implements ColaFactory{
    
    @Override
    public Cola newCola() {
        System.out.println("我是可乐工厂下面的可口可乐工厂");
        return new CocaCola();
    }
}

生产百事可乐的工厂:

/**
 *
 * 具体工厂2:百事可乐工厂
 */

public class PepsiColaFactory implements ColaFactory{

    @Override
    public Cola newCola() {
        System.out.println("我是可乐工厂下面的百事可乐工厂");
        return new PepsiCola();
    }
}

生产无糖可乐的工厂:

/*
 * 具体工厂3:无糖可乐工厂
 */

public class SugarFreeColaFactory implements ColaFactory{
    
    @Override
    public Cola newCola() {
        System.out.println("我是可乐工厂下面的无糖可乐工厂");
        return new SugarFreeCola();
    }
}

到这里目前有:

  • 一生产可乐的方法
  • 一个可乐工厂(下面有多个小工厂)
  • 三个生产三种类型可乐的方法(实现可乐接口)
  • 三个可乐工厂(生产三种可乐,实现可乐工厂接口)

测试类:

public class Test {
    public static void main(String[] args) {

        try{

            //新建一个可乐方法对象
            Cola a;

            //新建一个可乐工厂对象
            ColaFactory af;

            //告诉可乐工厂,你需要什么可乐,并且通知对应的分工厂
            af = (ColaFactory) new PepsiColaFactory();
            //执行对于生产方法
            a = af.newCola();
            a.cola();
            
        }catch (Exception e ){
            System.out.println(e.getMessage());
        }
    }
}

比如我现在需要百事可乐,我在af内传入百事可乐工厂:

我是可乐工厂下面的无糖可乐工厂
开始生产无糖可乐

如果传入CocaColaFactory

我是可乐工厂下面的可口可乐工厂
开始生产可口可乐

这就是工厂方法模式,和简单工厂模式有所不同,在这个模式内有一个抽象工厂接口,也就是你需要增加新产品后,不需要在原本的工厂内去修改代码,而是直接新建一个工厂,去实现抽象工厂即可,也是符合了开闭原则。

当然缺点也就是工厂多了,管理变得复杂,也增加了系统的抽象性和理解难度,而且抽象产品只能生产一种产品,但是此弊端可使用抽象工厂模式解决(抽象工厂模式在下一篇文章)

在这里插入图片描述


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK