IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 手把手教你学会使用设计模式之工厂模式 -> 正文阅读

[Java知识库]手把手教你学会使用设计模式之工厂模式

设计模式之工厂模式

简介

工厂模式称为工厂方法模式,是一种创建型设计模式,其在父类提供一个创建对象的方法,允许子类决定实例化对象的类型。

工厂模式是java中最常见的模式,本意是为了提高代码结构的拓展性,让外部更简单的调用。也是去掉if-else的一种解决方式,缺点是需要实现的类比较多。

工厂模式分为3种:工厂方法模式、简单/静态工厂模式、抽象工厂模式。

核心:将对象的创建和使用做分离。

未用设计模式实例

需求1

有一个花为电子厂,可以生产鼠标,假设我们通过按钮来点击触发生产。

在这里插入图片描述

代码如下:

/**
 * 花为电子厂,生产鼠标
 */
public void huaweiFactory() {
    System.out.println("生产鼠标");
}

调用方

public static void main(String[] args) {
    new Controller().huaweiFactory();
}

需求2

随着公司不断扩大,业务也更加广泛,该家电子厂也可以生产键盘。

在这里插入图片描述

我们一般会增加一个类型来区分。

代码如下:

/**
 * 花为电子厂,可以生产鼠标和键盘
 * @param type 1鼠标。2键盘
 */
public void huaweiFactory(Integer type) {
    if (type == 1) {
        System.out.println("生产鼠标");
    } else if (type == 2) {
        System.out.println("生产键盘");
    }
}

调用方

public static void main(String[] args) {
    //生产鼠标
    new Controller().huaweiFactory(1);
    //生产键盘
    new Controller().huaweiFactory(2);
}

需求3

业务又增加,该家电子厂可以生产耳机、数据线、充电宝。

在这里插入图片描述

代码如下:

/**
 * 花为电子厂
 * @param type 1鼠标、2键盘、3耳机、4数据线、5充电宝
 */
public void huaweiFactoryNew(Integer type) {
    if (type == 1) {
        System.out.println("生产鼠标");
    } else if (type == 2) {
        System.out.println("生产键盘");
    } else if (type == 3) {
        System.out.println("生产耳机");
    } else if (type == 4) {
        System.out.println("生产数据线");
    } else if (type == 5) {
        System.out.println("生产充电宝");
    }
}

调用方

public static void main(String[] args) {
    new Controller().huaweiFactoryNew(1);
    new Controller().huaweiFactoryNew(2);
    new Controller().huaweiFactoryNew(3);
    new Controller().huaweiFactoryNew(4);
    new Controller().huaweiFactoryNew(5);
}

小结

果然没有什么需求是 if-else 解决不了的,如果有,那就多写几个。但是也存在诸多问题:

  1. 实际代码逻辑肯定不是一行,可能几十行上百行,参数也不会是一个,也可能会根据类型增加不同的参数。当增加新的生产线后整个类会变得冗长,阅读难度增加,因为逻辑的不同也会导致难以维护。
  2. 该类职责过重,违反了单一职责
  3. 当增加新的生产时,需要修改原代码,调用方也需要修改,违反了开闭原则

这时,我们可以用工厂模式来进行优化。

简单/静态工厂模式

简介

简单/静态工厂模式一般我们叫简单工厂模式,由工厂对象决定创建哪个实例

对于需求2和需求3我们可以进行改进。

概览图

在这里插入图片描述

代码结构

在这里插入图片描述

代码

创建一个生产方法,子类可以生产鼠标、键盘等。

public interface ProductionService {
    /**
     * 生产
     */
    void production();
}

生产鼠标

public class MouseServiceImpl implements ProductionService {
    @Override
    public void production() {
        System.out.println("生产鼠标");
    }
}

生产键盘

public class KeyboardServiceImpl implements ProductionService {
    @Override
    public void production() {
        System.out.println("生产键盘");
    }
}

创建生产工厂,决定生产什么。

public class ProductionFactory {
    public ProductionService product(Integer type) {
        if (type == 1) {
            return new MouseServiceImpl();
        } else if (type == 2) {
            return new KeyboardServiceImpl();
        }
        return null;
    }
}

调用方

public class Controller {
    public static void main(String[] args) {
        new ProductionFactory().product(1).production();
        new ProductionFactory().product(2).production();
    }
}

新增需求

当需要增加需求3中的耳机时

流程图如下:

在这里插入图片描述

我们创建一个生产耳机的子类。

public class HeadsetServiceImpl implements ProductionService {
    @Override
    public void production() {
        System.out.println("生产耳机");
    }
}

在生产工厂增加类型3

public class ProductionFactory {
    public ProductionService product(Integer type) {
        if (type == 1) {
            return new MouseServiceImpl();
        } else if (type == 2) {
            return new KeyboardServiceImpl();
        } else if (type == 3) {
            return new HeadsetServiceImpl();
        }
        return null;
    }
}

调用方增加类型3即可。

public class Controller {
    public static void main(String[] args) {
        new ProductionFactory().product(1).production();
        new ProductionFactory().product(2).production();
        new ProductionFactory().product(3).production();
    }
}

小结

  1. 当增加新的生产线,只需要增加生产子类,修改工厂类,结构清晰。
  2. 只有一个具体工厂来创建对象,代码量较少。
  3. 不符合开闭原则,因为需要修改工厂类。

工厂方法模式

简介

在工厂方法模式中,核心的工厂类不再负责所有产品的创建,仅负责具体工厂子类必须实现的接口,将创建的工作交给子类。这样的好处是可以使在不修改具体工厂角色的情况下进行拓展

工厂方法模式是简单工厂模式的衍生、实现开闭原则可拓展。

工厂方法模式有四要素:

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

概览图

在这里插入图片描述

代码结构

在这里插入图片描述

代码

创建抽象产品类

public interface IProduction {
    /**
     * 生产接口
     */
    void production();
}

具体产品1:鼠标

public class MouseService implements IProduction {
    @Override
    public void production() {
        System.out.println("生产鼠标");
    }
}

具体产品2:键盘

public class KeyboardService implements IProduction {
    @Override
    public void production() {
        System.out.println("生产键盘");
    }
}

创建抽象工厂类

public interface IFactory {
    /**
     * 生产
     * @return
     */
    IProduction prod();
}

具体工厂1:鼠标

public class MouseFactory implements IFactory {
    @Override
    public IProduction prod() {
        return new MouseService();
    }
}

具体工厂2:键盘

public class KeyboardFactory implements IFactory {
    @Override
    public IProduction prod() {
        return new KeyboardService();
    }
}

调用方

public class Controller {
    public static void main(String[] args) {
        //鼠标
        IFactory mouseFactory = new MouseFactory();
        mouseFactory.prod().production();
        //键盘
        IFactory keyboardFactory = new KeyboardFactory();
        keyboardFactory.prod().production();
    }
}

新增需求

如果需要新增生产耳机。

在这里插入图片描述

则增加具体产品耳机和具体工厂耳机即可。

小结

  1. 明确了各个类的职责,结构清晰。
  2. 有新的产品增加,只需要增加具体产品和具体工厂即可。不会影响之前的代码,容易维护。
  3. 需要编写工厂代码,增加了工作量。类的数量增加,复杂度也会增加。

抽象工厂模式

简介

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品

和工厂方法模式一样,也是由抽象工厂、具体工厂、抽象产品和具体产品等4个要素组成,但是略有不同。

  1. 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品。
  2. 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
  3. 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
  4. 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。

实例

花为电子厂生产鼠标和键盘,公司发展越来越强大,收购了一家电子厂叫大米电子厂。这个电子厂也生产鼠标和键盘,总公司决定兼容一起生产。

第一个结论说过,没有什么需求是 if-else 解决不了的,如果有,那就多写几个。

代码如下:

/**
 * 花为和大米电子厂生产
 * @param num  1花为,2大米
 * @param type 1鼠标,2键盘
 */
public void huaweiAndDami(Integer num, Integer type) {
    if (num == 1) {
        if (type == 1) {
            System.out.println("花为电子厂,生产鼠标");
        } else if (type == 2) {
            System.out.println("花为电子厂,生产键盘");
        }
    } else if (num == 2) {
        if (type == 1) {
            System.out.println("大米电子厂,生产鼠标");
        } else if (type == 2) {
            System.out.println("大米电子厂,生产键盘");
        }
    }
}

调用方:

public static void main(String[] args) {
    new Controller().huaweiAndDami(1, 1);
    new Controller().huaweiAndDami(1, 2);
    new Controller().huaweiAndDami(2, 1);
    new Controller().huaweiAndDami(2, 2);
}

nice,只要 if-else 写的6,就没有实现不了的需求,实现不了就是 if-else 写的不够多。

针对上面的需求,我们就可以使用抽象工厂模式来优化。

概览图

在这里插入图片描述

代码结构

在这里插入图片描述

代码

大米相关

创建抽象产品类-大米

public interface IDami {
    void production();
}

创建具体产品类-鼠标

public class DMouseService implements IDami {
    @Override
    public void production() {
        System.out.println("大米电子厂,生产鼠标");
    }
}

创建具体产品类-键盘

public class DKeyboardService implements IDami {
    @Override
    public void production() {
        System.out.println("大米电子厂,生产键盘");
    }
}

创建抽象工厂类

public interface IDFactory {
    /**
     * 生产鼠标
     * @return
     */
    IDami mouse();

    /**
     * 生产键盘
     * @return
     */
    IDami keyboard();
}

创建具体工厂类

public class DFactoryService implements IDFactory {
    @Override
    public IDami mouse() {
        return new DMouseService();
    }

    @Override
    public IDami keyboard() {
        return new DKeyboardService();
    }
}
花为相关

创建抽象产品类-花为

public interface IHuawei {
    void production();
}

创建具体产品类-鼠标

public class HMouseService implements IHuawei {
    @Override
    public void production() {
        System.out.println("花为电子厂,生产鼠标");
    }
}

创建具体产品类-键盘

public class HKeyboardService implements IHuawei {
    @Override
    public void production() {
        System.out.println("花为电子厂,生产键盘");
    }
}

创建抽象工厂类

public interface IHFactory {
    /**
     * 生产鼠标
     * @return
     */
    IHuawei mouse();

    /**
     * 生产键盘
     * @return
     */
    IHuawei keyboard();
}

创建具体工厂类

public class HFactoryService implements IHFactory {
    @Override
    public IHuawei mouse() {
        return new HMouseService();
    }

    @Override
    public IHuawei keyboard() {
        return new HKeyboardService();
    }
}
调用方
public class Controller {
    public static void main(String[] args) {
        //花为电子厂
        IHFactory ihFactory = new HFactoryService();
        ihFactory.mouse().production();
        ihFactory.keyboard().production();
        //大米电子厂
        IDFactory idFactory = new DFactoryService();
        idFactory.mouse().production();
        idFactory.keyboard().production();

        //输出结果
//        花为电子厂,生产鼠标
//        花为电子厂,生产键盘
//        大米电子厂,生产鼠标
//        大米电子厂,生产键盘
    }
}

新增需求

如果或许又开了一家子工厂桔子,也生产鼠标键盘。

则如下图拓展即可。

在这里插入图片描述

不会影响之前的业务。

小结

  1. 当新增一个电子厂时,不需要修改原有代码,满足开闭原则。如增加桔子工厂。
  2. 当增加一个具体产品时,则所有的工厂类都需要进行修改,不满足开闭原则。如增加生产耳机。
  3. 当系统中只有一个电子厂时,抽象工厂模式就是工厂方法模式。

总结

  1. 简单工厂模式:由工厂对象决定创建哪个实例,实现简单,但是需要频繁修改工厂类,可能会引发新的bug,不符合开闭原则。
  2. 工厂方法模式:是简单工厂模式的拓展,结构清晰,拓展功能就是拓展工厂,不需要修改工厂类,但是增加了工作量。
  3. 抽象工厂模式:是工厂方法模式的拓展,在特定条件下才符合开闭原则。
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-18 15:50:19  更:2021-12-18 15:52:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:59:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码