Java设计模式 —— 【创建型模式】工厂模式(简单工厂、工厂方法模式、抽象工厂)详解

embedded/2024/11/29 21:44:58/

文章目录

  • 前言
  • 一、简单工厂(静态工厂)
      • 1、概述
      • 2、代码实现
      • 3、优缺点
  • 二、工厂方法模式
      • 1、概述
      • 2、代码实现
      • 3、优缺点
  • 三、抽象工厂模式
      • 1、概述
      • 2、代码实现
      • 3、优缺点
  • 四、总结


前言

先看个案例:【手机和手机店】在没有工厂的时候,手机店需要手机就需要自己创建,还得根据用户的选择进行创建不同的手机,如下图:
在这里插入图片描述
这样手机店直接与手机对象接触,就会对该对象耦合严重,假如我们添加新的手机品牌,还得修改手机店的create方法,这显然违背了软件设计的开闭原则。如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,将对象的创建封装在工厂内,实现使用者和对象解耦;所以说,工厂模式最大的优点就是:解耦

工厂模式的主要目的是将对象的创建过程封装在工厂类中,客户端代码只需要关心从工厂获取对象的过程,而不需要了解对象的创建细节。这样可以降低代码的耦合度,提高代码的可维护性和可扩展性


一、简单工厂(静态工厂)

1、概述

简单工厂不是一种设计模式,反而比较像是一种编程习惯。把对象的创建和业务逻辑层分开,实现使用方(手机店)与对象(手机)的解耦。但工厂和产品之间还是存在耦合关系。

主要包含以下角色:

  • 抽象产品: 定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品: 实现或者继承抽象产品的子类
  • 具体工厂: 提供了创建产品的方法,调用者通过该方法来获取产品。
    在这里插入图片描述

2、代码实现

抽象手机类【抽象产品】:

java">public abstract class Phone {public abstract String getName();
}

手机产品【具体产品】:

java">public class  HuaWei extends Phone {@Overridepublic String getName() {return "华为手机";}
}public class XiaoMi extends Phone {@Overridepublic String getName() {return "小米手机";}
}

手机工厂【具体工厂】:

java">public class Factory {public static Phone createPhone(String name) {Phone phone = null;if("小米".equals(name)) {phone = new XiaoMi();} else if("华为".equals(name)) {phone = new HuaWei();}return phone;}
}

手机店【使用者】:

java">public class Sotre {public static Phone orderPhone(String name) {return Factory.createPhone(name);}
}

测试:

java">public class Test {public static void main(String[] args) {Phone xiaomi = Sotre.orderPhone("小米");System.out.println(xiaomi.getName());Phone huawei = Sotre.orderPhone("华为");System.out.println(huawei.getName());}
}

在这里插入图片描述

3、优缺点

优点:

封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。

缺点:

增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。


二、工厂方法模式

1、概述

在在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体的工作交给子类去做。 定义一个用于创建对象的接口(抽象工厂),让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。很好的解决了简单工厂的问题,遵循开闭原则。

工厂方法模式的主要角色:

  • 抽象工厂: 提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
  • 具体工厂: 主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  • 抽象产品: 定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品: 实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

在这里插入图片描述

2、代码实现

抽象手机类【抽象产品】:

java">public abstract class Phone {public abstract String getName();
}

手机产品【具体产品】:

java">//小米手机
public class XiaoMi extends Phone {@Overridepublic String getName() {return "小米手机";}
}//华为手机
public class HuaWei extends Phone {@Overridepublic String getName() {return "华为手机";}
}

抽象工厂:

java">class interface PhoneFactory {Phone createPhone();
}

具体工厂:

java">//小米工厂
public class XiaoMiFactory implements PhoneFactory {@Overridepublic Phone createPhone() {return new XiaoMi();}
}//华为工厂
public class HuaWeiFactory implements PhoneFactory {@Overridepublic Phone createPhone() {return new HuaWei();}
}

手机店【使用者】:

java">public class Store {public Phone orderPhone(PhoneFactory factory) {return factory.createPhone();}
}

测试:

java">public class Test {public static void main(String[] args) {Store store = new Store();Phone huaWei = store.orderPhone(new HuaWeiFactory());Phone xiaomi = store.orderPhone(new XiaoMiFactory());System.out.println(xiaomi.getName());System.out.println(huaWei.getName());}
}

在这里插入图片描述

3、优缺点

优点:

  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
  • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;

缺点:

  • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。

三、抽象工厂模式

1、概述

抽象工厂模式是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。

抽象工厂模式工厂方法模式的升级版本,工厂方法模式只生产同一个等级的产品(小米手机,华为手机),而抽象工厂模式可生产多个等级的产品(小米家族,华为家族)。
在这里插入图片描述
抽象工厂模式的主要角色如下:

  • 抽象工厂: 提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品(小米工厂和华为工厂的所有功能的抽象【创建手机,创建路由器】)。
  • 具体工厂: 主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建(小米工厂造小米家族产品,华为工厂造华为家族产品)。
  • 抽象产品: 定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品(小米和华为所拥有的同一系列产品的抽象【手机产品,路由器产品】)。
  • 具体产品: 实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。

在这里插入图片描述

2、代码实现

抽象工厂:

java">public interface Factory {// 生产手机Phone createPhone();// 生产路由器Router createRouter();
}

具体工厂:

java">//小米工厂
public class XiaoMiFactory implements Factory {@Overridepublic Phone createPhone() {return new XiaoMiPhone();}@Overridepublic Router createRouter() {return new XiaoMiRouter();}
}//华为工厂
public class HuaWeiFactory implements Factory {@Overridepublic Phone createPhone() {return new HuaWeiPhone();}@Overridepublic Router createRouter() {return new HuaWeiRouter();}
}

抽象产品:

java">//手机产品
public abstract class Phone {public abstract String getName();
}//路由器类
public abstract class Router {public abstract String getName();
}

具体产品:

java">public class XiaoMiPhone extends Phone{@Overridepublic String getName() {return "小米手机";}
}public class HuaWeiPhone extends Phone {@Overridepublic String getName() {return "华为手机";}
}
java">public class XiaoMiRouter extends Router {@Overridepublic String getName() {return "小米路由器";}
}public class HuaWeiRouter extends Router {@Overridepublic String getName() {return "华为路由器";}
}

手机店:

java">public class Store {private Factory factory;public void setFactory(Factory factory) {this.factory = factory;}public Phone orderPhone(){return factory.createPhone();}public Router orderRouter(){return factory.createRouter();}
}

测试:

java">public class Test {public static void main(String[] args) {Store store = new Store();store.setFactory(new XiaoMiFactory());Phone xiaomiPhone = store.orderPhone();Router xiaomiRouter = store.orderRouter();System.out.println(xiaomiPhone.getName());System.out.println(xiaomiRouter.getName());System.out.println("===========");store.setFactory(new HuaWeiFactory());Phone huaweiPhone = store.orderPhone();Router huaweiRouter = store.orderRouter();System.out.println(huaweiPhone.getName());System.out.println(huaweiRouter.getName());}
}

在这里插入图片描述
如果要加同一个产品族的话,只需要再加一个对应的工厂类即可,不需要修改其他的类。

3、优缺点

优点:

当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:

当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。


四、总结

  1. 以上述案例为例,没有工厂就是手机店直接造手机,使用者和对象高度耦合,新增品类时违背开闭原则,一个手机店造不同手机违背单一职责原则;
  2. 由此引出简单工厂,手机店只需要和工厂打交道,售卖手机,不负责造手机的过程,实现手机店和对象的解耦,但是工厂和对象还是存在上述问题;
    在这里插入图片描述
  3. 由此工厂在向上抽象出“工厂规范”,形成工厂方法模式,不同的工厂负责不同的职责,添加新的品类时增加对应工厂和产品即可;
    在这里插入图片描述
  4. 在往下走,工厂做大做强以后,不只是可以生产手机,还添加了新的产品路由器,形成抽象工厂模式
    在这里插入图片描述
  5. 工厂方法模式是针对单一的品类进行的实现,二抽象工厂是针对多个品类(产品族)的实现。

http://www.ppmy.cn/embedded/141581.html

相关文章

小游戏聚合SDK的工具类封装

文章目录 前言工具类单例日志打印输入框的封装前言 之前的文章写了如何开发小游戏聚合SDK,既然是聚合SDK,工具类的封装也比较重要,做好基础搭建后续在接入其他渠道的时候能大大减少工作量。 工具类 单例 初始化的配置信息,比如应用ID 、渠道ID等需要全局使用,而且初始…

Leetcode 将有序数组转换为二叉搜索树

算法思想及代码解析: 这段代码的目的是将一个有序数组转换为 高度平衡的二叉搜索树(Balanced Binary Search Tree, BST)。以下是算法的详细解释: 1. 什么是高度平衡的二叉搜索树? 二叉搜索树:对于树中的每…

Web 端语音对话 AI 示例:使用 Whisper 和 llama.cpp 构建语音聊天机器人

大语言模型(LLM)为基于文本的对话提供了强大的能力。那么,能否进一步扩展,将其转化为语音对话的形式呢?本文将展示如何使用 Whisper 语音识别和 llama.cpp 构建一个 Web 端语音聊天机器人。 系统概览 如上图所示&…

selinux和防火墙实验

1 、 selinux 的说明 SELinux 是 Security-Enhanced Linux 的缩写,意思是安全强化的 linux 。 SELinux 主要由美国国家安全局( NSA )开发,当初开发的目的是为了避免资源的误用。 系统资源都是通过程序进行访问的,如…

Android.mk的变量有哪些

Android.mk 文件是 Android 构建系统中用于定义模块和依赖关系的 Makefile 文件。它使用一系列变量来指定源文件、库、编译选项等。以下是一些常用的 Android.mk 变量及其用途: 常用变量 模块名称 LOCAL_MODULE: 模块的名称,必须唯一。 LOCAL_MODULE : …

基于Matlab的图像去噪算法仿真

中值滤波的仿真 本节选用中值滤波法对含有高斯噪声和椒盐噪声的图像进行去噪,并用Matlab软件仿真。 (1)给图像加入均值为0,方差为0.02的高斯噪声,分别选择33模板、55模板和77模板进行去噪 Matlab部分代码&#xff1…

AI 编译器学习笔记之十三 -- Pytorch 特性实现

1、实现torch中的平铺特性 tile 的代码实现:Add support for aten.tile operator(not e2e support) by georgeuser Pull Request #2246 llvm/torch-mlir (github.com) torch.tile — PyTorch 2.5 documentation

U-Mamba/PyTorch WSL环境配置

Mamba的配置要求 LinuxNVIDIA GPUPyTorch 1.12CUDA 11.6https://github.com/state-spaces/mamba 个人版本: 通过Windows中的WSL来实现linux环境CUDA 12.4PyTorch 2.5.1Python 3.9 1、下载并配置WSL 微软应用商店搜索wsl选择合适的ubuntu版本进行下载在主板Bios…