简单工厂VS工厂方法

news2025/1/7 23:02:47

工厂方法模式–制造细节无需知

前面介绍过简单工厂模式,简单工厂模式只是最基本的创建实例相关的设计模式。在真实情况下,有更多复杂的情况需要处理。简单工厂生成实例的类,知道了太多的细节,这就导致这个类很容易出现难维护、灵活性差的问题。就像我们去饭店吃饭,只需要付钱,等成品,不需要了解这盘菜是怎么做的,如何加工的。

简单工厂

再来回顾下简单工厂模式的计算器功能的工厂类。

在这里插入图片描述

public static Operation createOperate(String operate) {
    Operation oper = null;
    switch (operate) {
        case "+":
            oper = new Add();
            break;
        case "-":
            oper = new Sub();
            break;
        case "*":
            oper = new Mul();
            break;
        case "/":
            oper = new Div();
            break;
    }
    return oper;
}

客户端调用时

Operation operate = OperationFactory.createOperate(strOperate);
double result = operate.getResult(numberA, numberB);

当使用工厂方法模式实现

实际就是对简单工厂中的细节部分进行再封装,让这个工厂类不需要知道很多的实现细节。是这样子吗,体验一下子。

结构图如下:

在这里插入图片描述

先构建一个工厂接口

public interface IFactory {
    Operation createOperation();
}

然后加减乘除的工厂都去实现这个接口,并实现自己的createOeration()方法

// 加法工厂
public class AddFactory implements IFactory {
    @Override
    public Operation createOperation() {
        return new Add();
    }
}

// 减法工厂
public class SubFactory implements IFactory {
    @Override
    public Operation createOperation() {
        return new Sub();
    }
}

// 乘法工厂
public class MulFactory implements IFactory {
    @Override
    public Operation createOperation() {
        return new Mul();
    }
}

// 除法工厂
public class DivFactory implements IFactory {
    @Override
    public Operation createOperation() {
        return new Div();
    }
}

那么在对外工厂类中就可以这么实现

public class OperationFactory {

    public static Operation createOperate(String operate) {
        Operation oper = null;
        IFactory factory = null;
        switch (operate) {
            case "+":
                factory = new AddFactory();
                break;
            case "-":
                factory = new SubFactory();
                break;
            case "*":
                factory = new MulFactory();
                break;
            case "/":
                factory = new DivFactory();
                break;
        }
        oper = factory.createOperation();
        return oper;
    }

}

当我需要增加新的运算功能时,需要增加运算类,运算工厂类,一下增加了好几个类,这样是不是变得更麻烦了?

简单工厂VS工厂方法

简单工厂模式的最大优点在于工厂类中包含必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。

就像计算器工厂类,客户端只需要传入一个"+"或别的,就能得到想要的功能算法。

但是当我们继续增加计算器功能时,比如增加一个指数运算,增加一个对数运算,要去不断修改OperationFactory类,就违背了开放-封闭原则。那我们该如何降低这种风险呢?就需要使用到工厂方法模式

我们应该尽量将长的代码分派切割成小段,再将每一小段封装起来,减少每段代码之间的耦合,这样风险就分散了,需要修改或扩展的难度就降低了。

再以计算器功能为例,项目起初,我们只知道加减乘除的功能,那我们就可以将这四个功能定义为基础运算工厂,也就是说前期功能是确定的,作为基础功能,我们就没有必要给加减乘除类增加冗余的工厂了。

后来增加了指数、对数运算,我们定义为高级运算工厂

那么其实并不是如上面的代码所讲,加减乘除功能每一个功能需要一个工厂类。而是将加减乘除用一个基础工厂来创建,而后面增加新的产品功能,又不想影响原有的工厂代码,于是就扩展一个新的工厂来处理即可。

工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到子类

修改结构图:

在这里插入图片描述

新增两个运算类(指数和对数)

// 指数
public class Pow extends Operation {
    @Override
    public double getResult(double numberA, double numberB) {
        return Math.pow(numberA, numberB);
    }
}

// 对数运算
public class Log extends Operation {
    @Override
    public double getResult(double numberA, double numberB) {
        return Math.log(numberB) / Math.log(numberA);
    }
}

工厂接口不变

public interface IFactory {
    Operation createOperation(String operType);
}

基础运算工厂类,此类已经比较成熟稳定,实现后应该封装到位,不建议轻易修改此类

public class FactoryBase implements IFactory {

    @Override
    public Operation createOperation(String operate) {
        Operation oper = null;
        switch (operate) {
            case "+":
                oper = new Add();
                break;
            case "-":
                oper = new Sub();
                break;
            case "*":
                oper = new Mul();
                break;
            case "/":
                oper = new Div();
                break;
        }
        return oper;
    }
}

高级运算工厂类,也许还有扩展产品的可能性

public class FactoryAdvanced implements IFactory {
    @Override
    public Operation createOperation(String operType) {
        Operation oper = null;
        switch (operType) {
            case "pow":
                oper = new Pow();
                break;
            case "log":
                oper = new Log();
                break;
        }
        return oper;
    }
}

那么最后一步就是对外工厂类,根据传入的参数,选择具体使用哪个工厂类。

public class OperationFactory {

    public static Operation createOperate(String operate) {
        Operation oper = null;
        IFactory factory = null;
        switch (operate) {
            case "+":
            case "-":
            case "*":
            case "/":
                factory = new FactoryBase();
                break;
            case "pow":
            case "log":
                factory = new FactoryAdvanced();
        }
        oper = factory.createOperation(operate);
        return oper;
    }

}

总结

工厂方法模式是简单工厂模式的进一步抽象和推广。工厂方法模式本质就是对获取对象过程的抽象。

对于复杂的参数的构造对象,可以很好地对外层屏蔽代码的复杂性,有很好的解耦能力。

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

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

相关文章

Eolink Apikit 版本更新:「数据字典」功能上线、支持 MongoDB 数据库操作、金融行业私有化协议、GitLab 生成 API 文档...

🎉 新增 搭建自定义接口协议架构,支持快速适配金融行业各类型私有协议的导入、编辑和展示。 数据字典功能上线,支持以数据字典的形式管理参数枚举值; 数据库连接支持 MongoDB 数据库操作; 基于 Apikit 类型导入 API…

DDD学习笔记

1)ddd: 软件复杂性的应对之道。 但是不是说:redis这种不会使用。 开发过程中,一直面临的一种复杂性。 是一种架构思想: 领域之间的组合。 让开发软件具有搭积木的感觉。 领域的核心是边界。 以领域划分为基础。 以通用语言为建设…

1-3 docker 安装 prometheus

一、环境 1、环境准备 安装Docker 镜像加速 安装 docker 检查版本 安装Docker-compose 二、Docker-compose 安装 Prometheus 1、【方式一】手动创建 docker-compose 和 配置文件 创建prometheus监控的文件夹 创建alertmanager的配置文件 - config.yml 新建grafana的…

YOLOv8 C2f模块融合shuffleAttention注意力机制

1. 引言 1.1YOLOv8直接添加注意力机制 yolov8添加注意力机制是一个非常常见的操作,常见的操作直接将注意力机制添加至YOLOv8的某一层之后,这种改进特别常见。 示例如下: 新版yolov8添加注意力机制(以NAMAttention注意力机制为例…

jsonlite库

jsonlite是一个R语言中用于处理JSON数据的库。它提供了一组简单而强大的函数,用于解析、生成和转换JSON数据。 使用jsonlite库,您可以轻松地将JSON数据解析为R语言中的数据结构,如列表或数据框。您还可以将R语言中的数据结构转换为JSON格式&…

解决vue3父组件执行子组件方法报错:TypeError: Cannot read properties of null

现象: 父组件执行子组件的代码: 原因: Vue3使用的所有变量除了来自父组件传值的props以外,其他的html绑定的所有本地变量都必须通过return导出! 这一点是vue3 最坑爹的一点。很容易忘记。 解决办法:使用t…

世界500强通信巨头全面推进SDLC,打造高质量的数字解决方案

某通信巨头是世界500强企业,全球领先的信息与通信技术解决方案供应商。多年来,该公司在数字化领域一直走在前列,打造了大量数字化创新解决方案和成功案例,助力合作伙伴更好地理解和应用数字化技术,实现自身的发展和价值…

c语言 简单认识 指针和结构体

指针 代码 #include <stdio.h>int main(){int a 10;//指针类型需要与变量的类型相同&#xff0c;且后面需要添加一个*符号&#xff08;注意这里不是乘法运算&#xff09;表示是对于类型的指针int * p &a; //这里的&并不是进行按位与运算&#xff0c;而是取…

Kubernetes 的四个网络挑战

Kubernetes 的主要职责之一是在应用程序之间共享节点。由于这些应用程序需要相互通信并与外部世界通信&#xff0c;因此网络是一个基本的需求。 Kubernetes 托管的分布式应用程序架构 来自 Kubernetes 集群外部的请求通常通过负责将它们代理到适当服务的路由器或 API 网关进行…

mac安装python3

文章目录 1. 安装1.1 brew安装&#xff08;失败&#xff09;2. 下载安装包 2. 查看版本3. 配置 1. 安装 1.1 brew安装&#xff08;失败&#xff09; brew install python3下载完成后报错&#xff1a;Error: python3.10: unknown or unsupported macOS version: :dunno 解决&a…

边缘计算助力低速无人驾驶驶入多场景落地快车道

自动驾驶刮起的风&#xff0c;如今正吹向低速无人驾驶赛道。近期不完全统计显示&#xff0c;当前A股及港股正在排队IPO的自动驾驶相关企业共有12家&#xff0c;其中实现盈利的企业仅两家&#xff0c;而且实现盈利的两家企业最主要的收入并不完全源于自动驾驶领域。 相比之下&am…

微信小程序webview中嵌套uniapp时的文件下载问题

文章目录 背景解决方案一、思路二、引入依赖三、H5端代码四、微信小程序端代码 效果图参考 前往闪闪の小窝以获得更好的阅读和评论体验 背景 这个标题就已经够抽象了吧 本来用微信小程序的web-view去嵌套h5已经因为微信的种种限制&#xff08;微信不希望你把微信小程序当做一…

五、计算机网络

&#xff08;一&#xff09;OSI/RM 七层模型 七层模型是计算机网络的基石&#xff0c;整个计算机网络是构建与七层模型之上的。 在数据链路层&#xff0c;数据开始以帧为单位&#xff0c;网卡的 MAC 地址就是数据帧的地址&#xff0c;数据的传输开始有地址了。 局域网是工作…

3.JMeter高级使用-让你与众不同

概述 今日目标&#xff1a; 插件下载与安装Basic Graphs 主要点 Average Response Time 平均响应时间Active Threads 活动线程数Successful/Failed Transactions 成功/失败 事务数 Additional Graphs 主要点 Response Codes 响应码Bytes Throughput 吞吐量Connect Times 连接…

【C++】类与对象 第三篇(初始化列表,explicit,static,友元,内部类)

再谈构造函数 构造函数体赋值 在创建对象时&#xff0c;编译器通过调用构造函数给对象各个成员变量一个合适的初始值 class Date{public:Date(int year, int month, int day){_year year;_month month;_day day;}​private:int _year;int _month;int _day;}; 虽然上述…

成语猜猜猜小程序源码系统 自带流量主功能帮你赚钱,带完整搭建教程

今天来给大家介绍一款成语猜猜猜小程序源码系统 。随着小程序生态的日益繁荣&#xff0c;越来越多的人开始关注小程序的开发和运营。成语猜猜猜作为一种具有趣味性和知识性的游戏形式&#xff0c;在小程序领域中备受欢迎。因此&#xff0c;开发一个成语猜猜猜小程序源码系统&am…

轻松理解 Transformers (3): Feed-Forward Layer部分

编者按&#xff1a;随着人工智能技术的不断发展Transformer架构已经成为了当今最为热门的话题之一。前馈层作为Transformer架构中的重要组成部分&#xff0c;其作用和特点备受关注。本文通过浅显易懂的语言和生活中的例子&#xff0c;帮助读者逐步理解Transformers中的前馈层。…

信息科技风险管理:合规管理、技术防控与数字化

信息科技对金融业务发展所起的作用是举足轻重的。近年来&#xff0c;金融机构在战略规划中相继引入科技引领的概念。作为金融机构信息科技从业人员&#xff0c;我们笃信信息科技是一个非常有用的工具&#xff0c;一个兼具产品思维和管理思维、拥有高质增效能力的工具。 这个工…

C语言 每日一题 PTA 11.6 day10

1.调和平均 N 个正数的算数平均是这些数的和除以 N&#xff0c;它们的调和平均是它们倒数的算数平均的倒数。 本题就请你计算给定的一系列正数的调和平均值。 输入格式&#xff1a; 每个输入包含 1 个测试用例。每个测试用例第 1 行给出正整数 N(≤1000)&#xff1b;第 2 行给…

c语言 结构体 简单实例

结构体 简单例子 要求&#xff1a; 结构体保存学生信息操作 代码 #include <stdio.h>//定义结构体 struct student{int ID;char name[20];char sex;char birthday[8];int grade; };int main(){int number;printf("请输入学生个数&#xff1a;");scanf(&quo…