设计模式之工厂模式

文章目录

  • 一、介绍
  • 二、基本组件
  • 三、案例应用
    • 1. 代码演示
    • 2. 优缺点
  • 四、静态工厂
    • 1. 应用
  • 五、总结

一、介绍

工厂模式(Factory Pattern)是最常使用的设计模式之一,属于创建型设计模式。在该设计模式中,我们不再使用new来实例化对象,而是通过工厂对象来获取指定的对象实例,其中对象的实例化过程是在工厂中完成的。换句话说,就是将对象的实例化过程从 调用方控制 改变成 工厂控制

说到这里,我愣了一下,这不就是控制反转(IOC)嘛?

大家回忆一下spring框架的IOC容器:spring的IOC容器主要使用的设计模式之一就是工厂模式,它将我们对对象的控制权转移给了BeanFactoryBeanFactory把实例化的对象放在单例池(即容器)中,当我们需要从spring中获取一个对象时,spring直接从该容器中获取对应的实例并返回给我们。

因此,我们使用工厂方法的目的是通过工厂提供一种统一的接口来创建不同类型的对象,将对象的创建过程与对象的使用过程分离,因为对象的创建过程是由工厂负责的,工厂只需要提供一个获取已创建的对象实例的方法。

二、基本组件

在我们使用工厂方法时,一般需要以下组件:

  • 工厂抽象。接口或抽象类,定义了工厂的行为。
  • 工厂实现类。对工厂的行为提供了具体实现。不同的工厂实现类用于创建不同的产品实现类。
  • 产品抽象。作为父类或接口,规定了一类具有相同行为的产品。
  • 产品实现类。产品抽象类的具体实现。

一般来讲,从工厂中获取的对象类型为抽象类型,其具体类型由工厂方法决定。

如下图所示

在这里插入图片描述

三、案例应用

我们举一个例子,有一个自行车公司(BicycleFactory),主要业务为生产自行车(Bicycle),该公司有两个工厂,专门生产哈罗单车(HaLuoBicycle)的工厂(HaLuoBicycleFactory) 和 专门生产美团单车(MeiTuanBicycle)的工厂(MeiTuanBicycleFactory)

其中,自行车公司(BicycleFactory)即为工厂抽象,提供create()方法生产自行车。哈罗单车工厂(HaLuoBicycleFactory) 和 美团单车工厂(MeiTuanBicycleFactory)作为工厂实现类。自行车(Bicycle)为产品抽象。哈罗单车(HaLuoBicycle) 和 美团单车(MeiTuanBicycle) 作为产品实现类。

如下图所示

在这里插入图片描述

1. 代码演示

下面我们通过代码模拟工厂模式的实现

  • 自行车公司(BicycleFactory)

    public interface BicycleFactory {/*** 生产单车* @return 抽象的单车*/public Bicycle create();
    }
    
  • 哈罗单车工厂(HaLuoBicycleFactory)

    public class HaLuoBicycleFactory implements BicycleFactory {/*** 生产哈罗单车* @return 哈罗单车*/@Overridepublic Bicycle create() {return new HaLuoBicycle();}
    }
    
  • 美团单车工厂(MeiTuanBicycleFactory)

    public class MeiTuanBicycleFactory implements BicycleFactory {/*** 生产美团单车* @return 美团单车*/@Overridepublic Bicycle create() {return new MeiTuanBicycle();}
    }
    
  • 自行车(Bicycle)

    public interface Bicycle {/*** 获取颜色* @return 颜色*/String getColor();/*** 获取品牌* @return 品牌*/String getBrand();
    }
    
  • 哈罗单车(HaLuoBicycle)

    public class HaLuoBicycle implements Bicycle {private final String color;private final String brand;public HaLuoBicycle() {System.out.println("哈罗单车被实例化");this.color = "蓝色";this.brand = "哈罗";}@Overridepublic String getColor() {return this.color;}@Overridepublic String getBrand() {return this.brand;}
    }
    
  • 美团单车(MeiTuanBicycle)

    public class MeiTuanBicycle implements Bicycle {private final String color;private final String brand;public MeiTuanBicycle() {System.out.println("美团单车被实例化");this.color = "黄色";this.brand = "美团";}@Overridepublic String getColor() {return this.color;}@Overridepublic String getBrand() {return this.brand;}
    }
    
  • 代码演示

    public static void main(String[] args) {// 实例化一个美团单车工厂BicycleFactory meiTuanFactory = new MeiTuanBicycleFactory();// 美团单车工厂生产美团单车Bicycle meiTuan = meiTuanFactory.create();System.out.println(meiTuan.getColor());System.out.println(meiTuan.getBrand());// 实例化一个哈罗单车工厂BicycleFactory haLuoFactory = new HaLuoBicycleFactory();// 哈罗单车工厂生产哈罗单车Bicycle haluo = haLuoFactory.create();System.out.println(haluo.getColor());System.out.println(haluo.getBrand());}
    
  • 输出结果

    在这里插入图片描述

2. 优缺点

从上面的代码演示中,我们可以总结出以下优缺点

优点:

  • 对象的创建过程与使用过程被解耦。如果被创建的对象结构复杂,则可以在工厂方法中完成该对象结构的组装。
  • 工厂方法返回的是产品抽象。因此我们无需关注产品细节,只需要按照产品抽象所定义的方法进行方法调用即可。
  • 当产品的创建过程需要修改时,我们只需在工厂方法中对创建逻辑进行修改即可,无需修改调用方的代码。
  • 适用于结构复杂的对象的创建场景。

缺点:

  • 虽然我们不再关注对象的创建过程,但是代价是需要关注工厂实例的创建过程。其实无论从代码层面还是现实层面来说,工厂对象一般只有一个,我们需要结合单例模式来处理对象工厂的创建和获取逻辑。
  • 一个工厂对象仅能创建一种产品。
  • 每当新增一个产品时,同样也需要创建对应的工厂类。这会导致项目中积累大量的工厂类和产品类。
  • 不适用于简单对象的创建。原本只需一行代码就能完成,而使用工厂模式就需要创建工厂类、工厂方法等,增加代码量。

四、静态工厂

由于工厂模式一般适用于创建复杂对象的场景。当我们需要创建简单对象时,使用工厂模式无疑是一种杀鸡用牛刀的方式。

静态工厂模式是工厂模式的衍生设计模式,用于创建简单的对象。

在静态方法中,只需要一个具体的产品类以及获取对应对象实例的静态方法。

使用上面的案例,我们以**美团单车(MeiTuanBicycle)**为例。在该类中添加一个静态方法create(),如下所示

public class MeiTuanBicycle implements Bicycle {private final String color;private final String brand;public MeiTuanBicycle() {System.out.println("美团单车被实例化");this.color = "黄色";this.brand = "美团";}@Overridepublic String getColor() {return this.color;}@Overridepublic String getBrand() {return this.brand;}/*** 静态工厂* @return*/public static Bicycle create() {return new MeiTuanBicycle();}
}public static void main(String[] args) {// 静态方法Bicycle bicycle = MeiTuanBicycle.create();System.out.println(bicycle.getColor());System.out.println(bicycle.getBrand());
}

输出结果如下:

在这里插入图片描述

1. 应用

静态工厂在jdk中的应用十分广泛,例如Integer.parseInt()方法:

public final class Integer extends Number implements Comparable<Integer> {// ...public static int parseInt(String s) throws NumberFormatException {return parseInt(s,10);}// ...
}

在该静态方法中,Integer类是工厂,它的静态方法parseInt接收字符串作为参数,返回一个Integer对象,因此Integer类又是产品

五、总结

本文介绍了创建型设计模式中的工厂模式和它的衍生设计模式静态工厂模式。并通过具体案例对其讲解,现在对这两中设计模式进行优缺点总结:

  • 工厂模式

    适用于创建复杂对象的场景,并将其创建过程和使用过程解耦

    • 优点
      • 对象的创建过程与使用过程被解耦。如果被创建的对象结构复杂,则可以在工厂方法中完成该对象结构的组装。
      • 工厂方法返回的是产品抽象。因此我们无需关注产品细节,只需要按照产品抽象所定义的方法进行方法调用即可。
      • 当产品的创建过程需要修改时,我们只需在工厂方法中对创建逻辑进行修改即可,无需修改调用方的代码。
      • 适用于结构复杂的对象的创建场景。
    • 缺点
      • 虽然我们不再关注对象的创建过程,但是代价是需要关注工厂实例的创建过程。其实无论从代码层面还是现实层面来说,工厂对象一般只有一个,我们需要结合单例模式来处理对象工厂的创建和获取逻辑。
      • 一个工厂对象仅能创建一种产品。
      • 每当新增一个产品时,同样也需要创建对应的工厂类。这会导致项目中积累大量的工厂类和产品类。
      • 不适用于简单对象的创建。原本只需一行代码就能完成,而使用工厂模式就需要创建工厂类、工厂方法等,增加代码量。
  • 静态工厂模式

    适用于创建复杂对象的场景。

    • 优点
      • 简单


纸上得来终觉浅,绝知此事要躬行。

————————我是万万岁,我们下期再见————————

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

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

相关文章

Mysql-InnoDB数据页结构

一、页结构说明 大致分7部分 二、记录在页中的存储 2.1 页面记录内存结构 行格式 存储到 User Records 部分&#xff0c;每当我们插入一条记录&#xff0c;都会从 Free Space 部分申请一个记录大小的空间划分到 User Records 部分 &#xff0c;用完则申请新的页&#xff1b; …

一网打尽java注解-克隆-面向对象设计原则-设计模式

文章目录 注解内置注解元注解 对象克隆为什么要克隆&#xff1f;如何克隆浅克隆深克隆 Java设计模式什么是设计模式&#xff1f;为什么要学习设计模式&#xff1f; 建模语言类接口类之间的关系依赖关系关联关系聚合关系组合关系继承关系实现关系 面向对象设计原则单一职责开闭原…

【LeetCode-中等题】53. 最大子数组和

题目 题解一&#xff1a;暴力解法&#xff1a; //暴力解法 每个元素为都循环一次&#xff0c;持续更新最大值int maxS Integer.MIN_VALUE;for(int i 0;i<nums.length;i){int num 0;for(int j i;j<nums.length;j){num numnums[j];maxS Math.max(maxS,num);}}retur…

SQL查询结果数字转字符串,以及查询结果的的四舍五入

最近在工作中碰到了SQL进行查询&#xff0c;碰到了SQL查询结果位数字型&#xff0c;需要把数字转化为字符串来进行下一步工作&#xff0c;整理结果如下: 先看图&#xff1a; 我们需要的查询data_val的和&#xff0c;这样的查询SQL如下: select sum(data_val) from 表名 where …

Docker安装Jenkins实操记录

前置条件&#xff1a; 1、安装了docker 2、安装了java&#xff08;没有安装情况下&#xff0c;可运行&#xff1a;yum install -y java-1.8.0-openjdk-devel.x86_64&#xff09; 一、拉取镜像 1、docker pull jenkins/jenkins 2、mkdir -p /usr/local/jenkins 3、chmod 777 …

使用端口映射实现Spring Boot服务端接口的公网远程调试:详细配置与步骤解析

文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…

Php“牵手”淘宝商品详情页数据采集方法,淘宝API接口申请指南

淘宝天猫详情接口 API 是开放平台提供的一种 API 接口&#xff0c;它可以帮助开发者获取商品的详细信息&#xff0c;包括商品的标题、描述、图片等信息。在电商平台的开发中&#xff0c;详情接口API是非常常用的 API&#xff0c;因此本文将详细介绍详情接口 API 的使用。 一、…

11、vue3

一、为什么要学 Vue3 1.1 为什么要学 Vue3 1.2 Vue3的优势 1.3 Vue2 选项式 API vs Vue3 组合式API Vue3 组合式API vs Vue2 选项式 API 二、create-vue搭建Vue3项目 2.1 认识 create-vue 2.2 使用create-vue创建项目 前提环境条件 已安装 16.0 或更高版本的 Node.js node -…

elementui的el-tabs标签页样式修改

一、官网样式&#xff1a; 二、修改样式 1.去掉下划线 效果&#xff1a; 代码: /* 去掉tabs标签栏下的下划线 */ ::v-deep .el-tabs__nav-wrap::after {position: static !important;/* background-color: #fff; */ } 2.改变下划线颜色 效果&#xff1a; 代码&#xff1a;…

压力监测设备——监测压力的仪器仪表

压力监测设备的原理和差压变送器相同&#xff0c;所不同的是压力监测设备低压室压力是大气压或真空。压力监测设备是一种接受压力变量&#xff0c;经传感转换后&#xff0c;按一定比例将压力变化转换成标准信号的仪表。 压力监测设备的输出信号传送到中央控制室进行压力指示和…

matlab面向对象

一、面向对象编程 1.1 面向过程与面向对象 区别&#xff1a; 面向过程的核心是一系列函数&#xff0c;执行过程是依次使用每个函数面向对象的核心是对象&#xff08;类&#xff09;及其属性、方法&#xff0c;每个对象根据需求执行自己的方法以解决问题 对象&#xff1a;单个…

leetcode 118.杨辉三角

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;https://leetcode.cn/problems/pascals-triangle/description/ 代码&#xff1a; class Solution { public:vector<vector<int>> generate(int numRows) {// 先开空间vector<vector<int>> v;v.…