设计模式详解(一):工厂方法——Factory Method

news2024/11/23 11:20:10

目录导航

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

工厂方法及其作用

工厂方法是一种创建型设计模式。所谓创建型设计模式是说针对创建对象方面的设计模式。在面向对象的编程语言里,我们通过对象间的相互协作,共同完成复杂的业务逻辑,因为对象之间存在着依赖关系。
当对象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
   @Override
   public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
       return new SubView(getContext());
   }
}

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

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

相关文章

【聚类算法】密度峰值聚类算法DPC(Density Peak Clustering Algorithm)

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 密度峰值聚类算法(Density Peak Clustering Algorithm),能够自动发现数据中的密度峰值点,并根据峰值点将数…

Java:创建文件夹并输出内容到文件中

前言 在实际开发当中我们往往会遇到需要用 Java 代码来进行在我们项目的部署的服务器上创建一个文件并向里面写入想要的数据,下面就是具体的实现方式,希望对小伙伴们有用。 代码 这里我把这个操作封装成了一个工具类,方便根据不同业务场景…

中国品牌在海外做独立站有什么优势?

从人口红利驱动转向消费升级驱动——品牌出海行业的变局正在上演,低价不再是适用于所有出海企业的策略。从产品出海走向真正意义上的品牌出海,正在成为一部分中国商家的选择。 无论是做品牌还是做全球化,都不容易。消费者购买的不止产品&…

从零开始 verilog 以太网交换机(六)帧处理单元设计与实现

从零开始 verilog 以太网交换机(六)帧处理单元设计与实现 🔈声明: 😃博主主页:王_嘻嘻的CSDN主页 🧨 从零开始 verilog 以太网交换机系列专栏:点击这里 🔑未经作者允许&a…

Android Java代码与JNI交互 JNI访问Java构造方法(九)

🔥 Android Studio 版本 🔥 🔥 创建包含JNI的类 JNIConstructorClass.java 🔥 package com.cmake.ndk1.jni;import com.cmake.ndk1.model.Animal;public class JNIConstructorClass {static {System.loadLibrary("constructor-class-lib");}public native…

深度学习——CNN卷积神经网络

基本概念 概述 卷积神经网络(Convolutional Neural Network,CNN)是一种深度学习中常用于处理具有网格结构数据的神经网络模型。它在计算机视觉领域广泛应用于图像分类、目标检测、图像生成等任务。 核心思想 CNN 的核心思想是通过利用局部…

环形链表(快慢指针)

给你一个链表的头节点 head ,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索…

C++ | 继承

目录 前言 一、继承的基本概念与使用 1、继承的概念 2、继承的定义 3、继承的访问限定符与继承方式 二、基类与派生类之间的赋值转换(切片) 三、继承中的作用域 1、继承中的作用域 2、隐藏(重定义) 四、派生类的默认构…

知识付费小程序怎么做

知识付费小程序是一种通过在线平台提供知识和教育内容的应用程序。下面将详细介绍其功能: 1. 音频视频课程: 知识付费小程序提供了丰富的音频和视频课程,在这些课程中,用户可以通过观看或听取专业讲师的讲解来学习各种知识领域。…

【文章系列解读】Nerf

1. Nerf NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis 2020年8月3日 (0)总结 NeRF工作的过程可以分成两部分:三维重建和渲染。(1)三维重建部分本质上是一个2D到3D的建模过程&#xff…

Java习题之实现平方根(sqrt)函数

目录 前言 二分查找 牛顿迭代法 总结 🎁博主介绍:博客名为tq02,已学C语言、JavaSE,目前学了MySQL和JavaWed 🎥学习专栏: C语言 JavaSE MySQL基础 🎄博主链接:tq02的…

【第四章 flutter-初识flutter】

文章目录 一、目录结构二、创建一个flutter项目三、创建自定义组件四、Container组件 就是divalignment 内容对齐方式decoration 类似border 为BoxDecoration的类 五、Text属性六、image组件总结、 一、目录结构 android、ios各自平台的资源文件 lib 项目目录 linux macos PC平…

Linux宝塔Mysql读写分离配置,两台服务器,服务器存在多个库

Linux宝塔Mysql读写分离配置,两台服务器,服务器存在多个库 一、主库操作 #登录数据库,用root登录方便,用其他账号会提示权限不足,需要登录root给予权限 mysql -u root -p 密码#创建一个账号,供从库用该账…

电商企业需要部署WMS仓储管理系统吗

随着电子商务行业的迅速发展,电商企业面临着日益增长的订单量和复杂的物流流程。为了提高仓储管理的效率和准确性,许多电商企业开始考虑部署WMS仓储管理系统。然而,是否真的需要部署WMS仓储管理系统,仍然是一个值得探讨的问题。本…

vLLM大模型推理加速方案原理(PagedAttention)

一、vLLM 简介 vLLM 用于大模型并行推理加速,核心是 PagedAttention 算法,官网为:https://vllm.ai/。 vLLM 主要特性: 先进的服务吞吐量通过 PagedAttention 对注意力 key 和 value 进行内存管理对传入请求的批处理针对 CUDA 内…

纯代码和低代码的本质区别

一、前言 纯代码和低代码是现代软件开发中两种不同的方法。 纯代码需要专业的编程技能,掌握编程语言、算法和数据结构等专业知识。而低代码则是一种新兴的开发方法,它大大降低了对编程技能的要求,让非技术人员也能够创建应用程序。随着低代码…

【SpringBoot】--03.数据访问、基础特性(外部化和内部外配置、整合JUnit)

文章目录 SpringBoot3-数据访问1.整合SSM场景1.1创建SSM整合项目1.2配置数据源1.3配置MyBatis1.4CRUD编写 2.自动配置原理3.扩展:整合其他数据源3.1 Druid 数据源 SpringBoot3-基础特性1. SpringApplication1.1 自定义 banner1.2.自定义 SpringApplication1.3Fluent…

nvm 管理node 环境配置

nvm安装: nvm(Node Version Manager)是一个用来管理node版本的工具。我们之所以需要使用node,是因为我们需要使用node中的npm(Node Package Manager),使用npm的目的是为了能够方便的管理一些前端开发的包!…

ColorOS凭什么夺冠?

摘要:五大主流安卓系统流畅度PK,谁的体验最好? 评价一款手机,你最先看的是什么? 是处理器平台?CPU核心频率?还是内存配置? 虽然这些硬件参数能够清晰地反映几款不同配置手机之间的性…

20230712-----阻塞IO驱动按键控制LED灯的亮灭

驱动程序 #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/cdev.h> #include <linux/slab.h> #include <linux/uaccess.h> #include <linux/of.h> #in…