设计模式详解(三):工厂方法

目录导航

  • 抽象工厂及其作用
  • 工厂方法的好处
  • 工厂方法的实现
    • 关系图
    • 实现步骤
  • 工厂方法的适用场景
  • 工厂方法举例

抽象工厂及其作用

工厂方法是一种创建型设计模式。所谓创建型设计模式是说针对创建对象方面的设计模式。在面向对象的编程语言里,我们通过对象间的相互协作,共同完成复杂的业务逻辑,因为对象之间存在着依赖关系。
当对象A依赖对象B时,我们不采取直接创建对象B的方式,即B productB = new B()

public class A {public void bizLogic(){//do something...B b = new B();//do something...}
}

而是在A的父类中定义一个返回B类型对象的方法,通常该方法的返回值是接口类型或者BaseClass类型,允许A的子类覆盖该方法,返回不同的对象类型C,但需满足C extends/implements B。在父类A中,该方法既可以是抽象方法,也可以不定义为抽象方法(返回默认的B类型实例)。

public abstract class A {public void bizLogic(){//do something...B b = createB();//do something...}public abstract B createB();
}

这种创建对象的设计模式称之为工厂方法。为什么叫工厂方法?通常对象被称之产品,而生产产品的工具称之为工厂,由于在这种设计模式中,是一个方法承担工厂的作用,所以称之为工厂方法。

工厂方法的好处

乍一看,似乎我们只是把创建对象B的代码抽取到了一个方法中而已,实际上这种设计模式有着诸多好处。

  • 解耦。避免对象A与被依赖方B的具体实现类强耦合,对于A来说,我只需要一个B类型的实例,并不关心具体实现类,利于程序扩展。
  • 符合单一职责的原则。类的设计原则之一便是单一职责。A的主要职责肯定不是创建B对象,而是依赖B对象完成特定的业务功能。将创建B的代码单独抽离,使得A的职责更加清晰。
  • 符合开闭原则。后续可以引入多个B的子类而不会“惊动”A的代码。

工厂方法的实现

关系图

依赖方A我们称之为Creator,即需要创建产品B的类,被依赖方B称之为Product,即产品。它们的关系图如下:

在这里插入图片描述

实现步骤

  1. 为对象B定义一个统一的接口B_interface或基类B_base_class,并在其中定义对外提供功能的统一接口方法,定义一批B的子类,以实现差异化功能,所有的子类需实现B_interface或继承B_base_class
  2. 在对象A的父类中定义一个返回B对象的方法,返回值类型为B_interfaceB_base_class。该方法可为抽象方法,也可返回默认的B实例,视实际使用需求而定。
  3. 将对象A中直接创建对象B的代码全部替换成定义好的工厂方法。
  4. 定义一批A的子类,在子类中重写工厂方法,返回不同的B实例。

工厂方法的适用场景

  1. 当我们实现业务代码时,无法提前获知所依赖对象的具体类型,这通常发生在顶层设计的时候,此时可以通过工厂方法抽象定义所需的对象。
  2. 我们打包一个库给他人使用时,其中一些业务逻辑,我们无法确定用户是应该使用库里定义好的一些默认组件,还是想使用自己扩展后的组件(继承默认组件),可通过工厂方法解决该问题。
  3. 被依赖的对象可能比较特殊,占用一定的系统资源,所以不能任意创建,可在工厂方法内实现一定的控制逻辑,控制对象的创建过程,避免资源浪费。

工厂方法举例

工厂方法在代码设计中几乎无处不在,这里举一个Android中的例子。我们在创建Fragment时都要继承Fragment基类,并实现onCreateView方法,该方法负责创建一个视图对象,由于基类并不清楚子类会返回一个什么样的视图对象,所以该方法是一个工厂方法,返回值定义为基类View

public class SubFragment extends Fragment {@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {return new SubView(getContext());}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能优化算法应用:基于教与学算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于教与学算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于教与学算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.教与学算法4.实验参数设定5.算法结果6.参考文献7.…

leetCode 78.子集 + 回溯算法 + 图解

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集 示例 1: 输入:nums [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1…

STM32---时钟树

写在前面:一个 MCU 越复杂,时钟系统也会相应地变得复杂,如 STM32F1 的时钟系统比较复杂,不像简单的 51 单片机一个系统时钟就 可以解决一切。对于 STM32F1 系列的芯片,其有多个时钟源,构成了一个庞大的是时…

Python 异常处理(try except)

文章目录 1 概述1.1 异常示例 2 异常处理2.1 捕获异常 try except2.2 抛出异常 raise 3 异常类型3.1 内置异常3.2 自定义异常 1 概述 1.1 异常示例 异常:程序执行中出现错误,若不处理,则程序终止 示例代码: v 6 / 0 # 除数不…

Redis入门指南学习笔记(3):Redis高级特性

一.前言 上一篇博客对Redis常用的数据结构进行了详细介绍。Redis除了丰富的数据类型支持,还包含许多高级特性,例如事务、内存驻留策略、排序、消息队列等,本文将对这些进行逐一介绍。 二.事务 Redis同样包含事务(transaction&a…

【刷题笔记】H指数||数组||二分查找的变体

H指数 最新编辑于2023.11.29 之前的代码写得有点抽象,实在抱歉,好像我自己都不理解当时自己怎么写的,现在重新更新了代码,保证好理解。 1 题目描述 https://leetcode.cn/problems/h-index/ 给你一个整数数组 citations &#xf…

Python基础学习之包与模块详解

文章目录 前言什么是 Python 的包与模块包的身份证如何创建包创建包的小练习 包的导入 - import模块的导入 - from…import导入子包及子包函数的调用导入主包及主包的函数调用导入的包与子包模块之间过长如何优化 强大的第三方包什么是第三方包如何安装第三方包 总结关于Python…

【人工智能Ⅰ】实验3:蚁群算法

实验3 蚁群算法的应用 一、实验内容 TSP 问题的蚁群算法实现。 二、实验目的 1. 熟悉和掌握蚁群算法的基本概念和思想; 2. 理解和掌握蚁群算法的参数选取,解决实际应用问题。 三、实验原理 1.算法来源 蚁群算法的基本原理来源于自然界…

网络基础_1

目录 网络基础 协议 协议分层 OSI七层模型 网络传输的基本流程 数据包的封装和分用 IP地址和MAC地址 网络基础 网络就是不同的计算机之间可以进行通信,前面我们学了同一台计算机之间通信,其中有进程间通信,前面学过的有管道&#xff…

在Linux上安装KVM虚拟机

一、搭建KVM环境 KVM(Kernel-based Virtual Machine)是一个基于内核的系统虚拟化模块,从Linux内核版本2.6.20开始,各大Linux发行版就已经将其集成于发行版中。KVM与Xen等虚拟化相比,需要硬件支持的完全虚拟化。KVM由内…

百度人工智能培训第二天笔记

参加了百度人工智能初步培训,主要是了解一下现在人工智能的基本情况,以便后续看可以参与一些啥? 下面就继续前一天的内容记录。 一、先做电动自行车的电梯里检测 先进行图片资料的上传与标注,这个昨天的最好也说了一下。 训练完后…

手摸手Element-ui组件化开发

前端环境准备 编码工具: VSCode 依赖管理:NPM 项目构建: Vuecli NPM的全称是Node Package Manager,是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准。2020年3月17日,Github宣布收购npm&am…

WebGL/threeJS面试题扫描与总结

什么是 WebGL?什么是 Three.js?请解释three.js中的WebGL和Canvas的区别? WebGL(全写Web Graphics Library)是一种3D绘图协议,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个…

龙芯loongarch64服务器编译安装pyarrow

1、简介 pyarrow是一个高效的Python库,用于在Python应用程序和Apache Arrow之间进行交互。Arrow是一种跨语言的内存格式,可以快速高效地转移大型数据集合。它提供了一种通用的数据格式,将数据在内存中表示为表格,并支持诸如序列化和分布式读取等功能。 龙芯的Python仓库安…

【教程】 一文部署配置并入门 Redis

综述 什么是Redis Redis官网——Redis.io Redis, 作为一个高性能的键值对数据库,主要应用于以下场景: 缓存系统:由于其高速读写能力,Redis 非常适合用作缓存系统,减少数据库负载。 会话存储(Session St…

构建未来:云计算 生成式 AI 诞生科技新局面

目录 引言生成式 AI:开发者新伙伴云计算与生成式 AI 的无缝融合亚马逊云与生成式 AI 结合的展望/总结我用亚马逊云科技生成式 AI 产品打造了什么,解决了什么问题未来科技发展趋势:开发者的机遇与挑战结合实践看未来结语开源项目 引言 2023年…

基于SpringBoot母婴商城

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本母婴商城系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息&am…

04.里氏替换原则(Liskov Substitution Principle)

暴论:一般的,如果一个富二代不想着证明自己,那么他一辈子都会衣食无忧。 一言 里氏替换原则想告诉我们在继承过程中会遇到什么问题,以及继承有哪些注意事项。 概述 这是流传较广的一个段子: “一个坐拥万贯家财的富二…

DBS note6:Hashing(哈希存储)

目录 一、一般策略 二、算法简述 三、哈希缺点(Drawbacks of Hashing) 四、举例 五、外部哈希的分析 一、一般策略 由于我们无法一次性将所有数据放入内存中,我们需要构建多个不同的哈希表并将它们连接在一起。然而,这个想法…

第20 章 多线程

20.1线程简介. 20.2创建线程 2.1继承Thread类 Thread 类是java.lang包中的一个类,从这个类中实例化的对象代表线程,程序员启动一个新线程需要建立Thread 实例。Thread类中常用的两个构造方法如下: public Thread():创建一个新的线程对象。 public Threa…