Java设计模式-创建者模式-工厂模式

news2024/11/28 4:45:28

工厂模式

  • 工厂模式
    • 简单工厂模式
    • 工厂方法模式
    • 抽象工厂模式

工厂模式

要求:由一个特定的工厂提供所需的对象,由工厂来完成对象的创建
工厂模式一般分为三种:简单工厂模式工厂方法模式抽象工厂模式
其中简单工厂模式不属于23种设计模式

简单工厂 : 用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)
抽象工厂 :用来生产不同产品族的全部产品。(支持拓展增加产品;支持增加产品族)

简单工厂模式

简单工厂模式就是 定义了一个创建对象的类,让这个类来封装实例化对象的行为
特点:只有一个工厂,根据入参,通过硬编码的方式创建所需对象。不方便扩展,不建议用
假设:我要开一个小店,卖牛肉包子,猪肉包子
分析上述需求,我们用简单工厂模式实现,如下:

/**
 * 抽象包子类
 **/
public interface Bun {
    void pack();//打包
}

/*************************************************************************/

public class BeefBun implements Bun {
    public BeefBun() {
        System.out.println("包牛肉包");
    }

    @Override
    public void pack() {
    }
}

/*************************************************************************/
public class PorkBun implements Bun {
    public PorkBun() {
        System.out.println("包猪肉包");
    }

    @Override
    public void pack() {
    }
}

/*************************************************************************/
/**
 * 简单包子工厂
 **/
public class BunFactory {

    public Bun createBun(String type){
        Bun bun = null;
        switch (type){
            case "beef":
                bun = new BeefBun();
                break;
            case "pork":
                bun = new PorkBun();
                break;
            default:
                throw new RuntimeException("我不会做");
        }
        return bun;
    }
}

上述代码通过包子工厂 BunFactory,根据入参选择生产不同种类的包子,实现了工厂模式,隐藏了生产细节
测试代码如下:

public class MyStore01 {
    /**
     * 简单工厂模式
     * 只有一个工厂
     */
    BunFactory factory = new BunFactory();


    public Bun order(String type){
        Bun bun = factory.createBun(type);
        //打包...等操作
        bun.pack();
        return bun;
    }
}


/*************************************************************************/
@Test
public void client01(){
    MyStore01 myStore = new MyStore01();
    Bun beef = myStore.order("beef");
    Bun pork = myStore.order("pork");
}
输出:
包牛肉包
包猪肉包

上述代码完成了简单工厂模式的使用,可以隐藏实例的创建,通过工厂对实例进行创建。
但是设想一下,如果需要扩展功能怎么办
假设,我的小店 又要做 香菇菜包,那么势必要修改 BunFactory的代码,很明显,这违反了开闭原则。
那么接下来我们看下 工厂方法模式

工厂方法模式

定义多个工厂,每个工厂生产一种产品
特点:有多个工厂,工厂抽象化,一个具体工厂只生产一个具体产品,容易类爆炸
还是针对上面的需求,开一个小店,卖牛肉,猪肉包子
使用工厂方法模式,实现如下:

/**
 * 抽象包子类
 **/
public interface Bun {
    void pack();//打包
}

/*************************************************************************/

public class BeefBun implements Bun {
    public BeefBun() {
        System.out.println("包牛肉包");
    }

    @Override
    public void pack() {
    }
}

/*************************************************************************/
public class PorkBun implements Bun {
    public PorkBun() {
        System.out.println("包猪肉包");
    }

    @Override
    public void pack() {
    }
}

/*************************************************************************/
/**
* 抽象包子工厂
*/
public interface BunFactory {
    Bun createBun();
}

/*************************************************************************/
/**
* 牛肉包子工厂
*/
public class BeefBunFactory implements BunFactory{
    @Override
    public Bun createBun() {
        return new BeefBun();
    }
}

/*************************************************************************/
/**
* 猪肉包子工厂
*/
public class PorkBunFactory implements BunFactory {
    @Override
    public Bun createBun() {
        return new PorkBun();
    }
}

测试代码:

public class MyStore02 {
    /**
     * 工厂方法模式
     * 有多个工厂,一个工厂只产一种产品
     * @param type
     * @return
     */
    BunFactory factory;

    public void setFactory(BunFactory factory) {
        this.factory = factory;
    }

    public Bun order(){
        Bun bun = factory.createBun();
        //打包...等操作
        bun.pack();
        return bun;
    }
}

@Test
public void client02(){
    MyStore02 myStore = new MyStore02();
    myStore.setFactory(new BeefBunFactory());
    myStore.order();
    myStore.setFactory(new PorkBunFactory());
    myStore.order();
}

输出:
包牛肉包
包猪肉包

上述代码完成了 和简单工厂模式相同的功能,
但是使用工厂方法模式,可以不修改原有代码,通过增加工厂类的方式来扩充功能。

例如:我想增加青菜包的业务,只需要实现一个青菜包类 和 青菜包工厂即可

但是,我们再想一下,新增一个功能要加两个类,如果后面业务越来越广泛,类是不是越来越多,是不是 容易类爆炸。
再思考一下,一个工厂只生产一种产品是不是太浪费了。难道又要回到简单工厂模式了?

当然不是,我们可以折中一下,对工厂类进行更深层的抽象。对产品进行划分,让一个工厂可以生产多种产品,这些产品都是同一组的,相关联的。

下面看下抽象工厂模式

抽象工厂模式

提供一个生产一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

抽象工厂模式比工厂方法模式的抽象程度更高。在工厂方法模式中每一个具体工厂只需要生产一种具体产品,但是在抽象工厂模式中一个具体工厂可以生产一组相关的具体产品,这样一组产品被称为产品族。产品族中的每一个产品都分属于某一个产品继承等级结构。

特点:多个工厂,工厂进行更高层次的抽象,每个工厂生产一个产品族(生产一组相关的具体产品

先引入两个概念:产品族,产品等级结构

  • 产品族:一组相关的具体产品(如海尔旗下的众多产品)。
  • 产品等级结构:每一个产品族都分属于某一个产品继承等级结构(如空调下的多种品牌)。

在前面的工厂方法模式中,考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机。工厂方法模式只考虑生产同等级(同种类被称为同等级)的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如农场里既养动物又种植物,电器厂既生产电视机又生产洗衣机或空调。而抽象工厂模式就考虑了多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,如图所示的是海尔工厂和 TCL 工厂所生产的电视机与空调对应的关系图。
在这里插入图片描述
还是针对我的包子店的需求,我扩充了牛奶的需求。
使用抽象工厂模式开发如下:


/**
 * 抽象包子类
 **/
public interface Bun {
    void pack();//打包
}

/*************************************************************************/

public class BeefBun implements Bun {
    public BeefBun() {
        System.out.println("包牛肉包");
    }

    @Override
    public void pack() {
    }
}

/*************************************************************************/
public class PorkBun implements Bun {
    public PorkBun() {
        System.out.println("包猪肉包");
    }

    @Override
    public void pack() {
    }
}

/*************************************************************************/
/**
*抽象牛奶类
*/
public interface Milk {
    void pack();//打包
}

/*************************************************************************/
public class PureMilk implements Milk{
    public PureMilk() {
        System.out.println("做一杯纯牛奶");
    }

    @Override
    public void pack() {
    }
}

/*************************************************************************/
public class BreakfastMilk implements Milk{
    public BreakfastMilk() {
        System.out.println("做一杯早餐奶");
    }

    @Override
    public void pack() {
    }
}

/*************************************************************************/
/**
*抽象工厂类
*/
public interface Factory {
    Bun createBun();
    Milk createMilk();
}

/*************************************************************************/
/**
*具体工厂类1号,生产牛肉包和纯牛奶
*/
public class PureBeefFactory implements Factory{
    @Override
    public Bun createBun() {
        return new BeefBun();
    }

    @Override
    public Milk createMilk() {
        return new PureMilk();
    }
}

/*************************************************************************/
/**
*具体工厂类2号,生产猪肉包和早餐奶
*/
public class BreakfastPorkFactory implements Factory{
    @Override
    public Bun createBun() {
        return new PorkBun();
    }

    @Override
    public Milk createMilk() {
        return new BreakfastMilk();
    }
}

上述代码中,纯牛奶和牛肉包被看作一个产品族
纯牛奶和早餐奶被看成一个产品等级结构
测试代码:

public class MyStore03 {
    /**
     * 抽象工厂模式
     * 有多个工厂,一个工厂生产一个产品族
     * @param type
     * @return
     */
    Factory factory;

    public void setFactory(Factory factory) {
        this.factory = factory;
    }

    public Bun orderBun(){
        Bun bun = factory.createBun();
        //打包...等操作
        bun.pack();
        return bun;
    }

    public Milk orderMilk(){
        Milk milk = factory.createMilk();
        milk.pack();
        return milk;
    }
}


/*************************************************************************/
/**
 * 抽象工厂模式
 */
@Test
public void client03(){
    MyStore03 myStore = new MyStore03();
    myStore.setFactory(new PureBeefFactory());
    myStore.orderBun();
    myStore.orderMilk();
}
输出:
包牛肉包
做一杯纯牛奶

上述抽象工厂实现了一个工厂创建多个产品的功能,与简单工厂类似,自然有简单工厂类似的缺点:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1192579.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第三方支付支付宝的信息安全分析

随着信息技术的进步,网络结算方式也在迅速发展。网上结算虽然便捷快速,但是如果没有保障的平台或者法律的支持,双方在没有约束的情况下,就会导致拖延、折扣或者拒付等许多经济事件的发生,由此第三方支付就随之产生。第…

三目运算符与if 判断语句的区别

我们用一个案例解释python的判断语句: if a > b :return aelse:return b案例: a 2b 3if a > b:max aelse:max b这样利用python语言,写一个if 判断没有问题吧 三目运算符 下面我们用三目运算符来完成这样一…

Win10专业版安装wsl-ubuntu子系统

文章目录 一、查看是否满足安装要求二、管理员权限启动 Windows PowerShell三、启用Windows10子系统功能四、启用虚拟机平台功能五、重启电脑六、下载 Linux 内核更新包(适用于 x64 计算机的 WSL2 Linux 内核更新包)七、将 WSL 2 设置为默认版本八、打开…

台灯护眼灯哪个牌子好?护眼台灯品牌型号推荐榜单

台灯可以说家家必备!家中有上学的小孩更是需要一款好台灯,因为看书、写字、做作业都离不开台灯,一款好的台灯不仅会提供明亮的学习环境,而且还能保护视力,预防近视,因此,挑选台灯绝对不可以马虎…

React Native适配Xcode 15 iOS 17.0+

iOS 17.0 Simulator(21A328)下载失败 App Store 更新到 Xcode15 后,无法运行模拟器和真机。需要下载iOS 17对应的模拟器。Xcode中更新非常容易中断失败,可以在官网单独下载iOS 17模拟器文件,例如:iOS_17.0.1_Simulator_Runtime.d…

React 递归手写流程图展示树形数据

需求 根据树的数据结构画出流程图展示,支持新增前一级、后一级、同级以及删除功能(便于标记节点,把节点数据当作label展示出来了,实际业务中跟据情况处理) 文件结构 初始数据 [{"ticketTemplateCode": &…

Vite - 配置 - 不同的环境执行不同的配置文件

目标描述 通过不同的命令,执行不同的环境的配置文件中的内容: npm run dev : 执行开发环境的配置文件 npm run build: 执行生产环境的配置文件 环境文件准备 为了在不同的环境中使用不同的配置文件,我们将配置文件拆分开来。 开发环境使用开发…

【Python基础】基于UPD协议实现简易聊天室(Socket编程)

UDP通信 1.什么是 socket2. 创建 socket3.udp 网络程序-发送、接收数据(User Datagram Protocol)udp 网络程序-发送、接收数据(客户端)udp 绑定信息udp 绑定信息---服务器端总结 4.udp 聊天器 1.什么是 socket socket(简称 套接字…

如何快速编写测试用例?

当你学会了如何设计测试用例之后,接下来便是开始用例的编写。 在设计阶段,更准确的说应该是识别测试点的过程,而编写阶段则是将测试点细化成一条条测试用例的过程,有了比较全的用例场景后,如何让别人更舒服、更方便、…

Python + UnitTest 软件测试流程总结

以测试用户登录流程为例: TestCase: TestCase 主要用来编写测试用例,这里结合 断言(assertEqual 和 assertIn) 进行判断,避免了手动书写判断。 # tools.py # 登录验证方法 def login(username, password…

Android Studio导入,删除第三方库

Android项目经常用到无私的程序员们提供的第三方类库。本篇博客就是实现第三方库的导入和删除。 一、导入第三方库 1、将需要的库下载到本地; 2、新建Moudle (1)File --- New Moudle (2)选择Android Library --- Next (3)填写Moudle名 --- Finish。一个新的Mou…

【优选算法系列】【专题七分治】第一节.75. 颜色分类和912. 排序数组

文章目录 前言一、颜色分类 1.1 题目描述 1.2 题目解析 1.2.1 算法原理 1.2.2 代码编写二、排序数组 2.1 题目描述 2.2 题目解析 2.2.1 算法原理 2.2.2 代码编写总结 前言 一、颜色分类 1.1 题目描述 描述&…

QML9、输入元素

1、输入元素(Input Element) 我们已经使用过MouseArea(鼠标区域)作为鼠标输入元素。这里我们将更多的介绍关于键盘输入的一些东西。我们开始介绍文本编辑的元素:TextInput(文本输入)和TextEdit(文本编辑)。 2、文本输入(TextInput) 文本输入允许用户输入一行文本…

Redis之缓存

文章目录 前言一、缓存使用缓存的原因 二、使用缓存实现思路提出问题 三、三大缓存问题缓存穿透缓存雪崩缓存击穿互斥锁实现逻辑过期时间实现 总结 前言 本篇文章即将探索的问题(以黑马点评为辅助讲解,大家主要体会实现逻辑) 使用redis缓存的…

Nmap-NSE

一.Nmap的脚本引擎类别 参数说明ALL允许所有的脚本Auth认证Default默认的脚本引擎,-sC:equivalent to --script default 或 --script default ,执行一些脚本的脚本扫描Discovery发现,获取目标的深度信息External扩展&#xff0c…

2023面试笔记四

1、gc导致的cpu冲高 排查是否为gc导致,看如下两点: gc频率和耗时 内存占用率 (1)gc频率和耗时有两种手段看: 第一种:根据gc日志的打印时间,可确定每次gc间隔的时间和耗时: 使用…

聚铭国产化日志合规版 → 中小企事业单位等保建设的最优解

聚铭网络最新发布聚铭综合日志分析系统国产化合规版本 ,相较于同类型同档次非国产化设备性能无衰减、功能无裁减、成本不提高,适用于信创替换以及等保日志建设等应用场景。 面对日趋复杂的外部环境,近年来,国家越来越重视关键技术…

谭浩强【C语言程序设计】第一章习题详解

目录 1,什么是程序?什么是程序设计? 2,为什么需要计算机语言?高级语言有哪些特点? 3,正确理解以下名词及其含义: (1)源程序,目标程序,可执行程序。 (2)程…

免费小程序HTTPS证书

随着互联网的快速发展,小程序已经成为人们日常生活中不可或缺的一部分。然而,在小程序的开发和使用过程中,安全问题一直是开发者们关注的重点。其中,HTTPS 证书是保障小程序安全的重要工具之一。在这方面,免费的小程序…

【机器学习】正则化到底是什么?

先说结论:机器学习中的正则化主要解决模型过拟合问题。 如果模型出现了过拟合,一般会从两个方面去改善,一方面是训练数据,比如说增加训练数据量,另一方面则是从模型角度入手,比如,降低模型复杂…