01-Spring中的工厂模式

news2024/11/16 17:36:18

工厂模式

工厂模式的三种形态: 工厂模式是解决对象创建问题的属于创建型设计模式,Spring框架底层使用了大量的工厂模式

  • 第一种:简单工厂模式是工厂方法模式的一种特殊实现,简单工厂模式又叫静态工厂方法模式不属于23种设计模式之一
  • 第二种:工厂方法模式, 是23种设计模式之一
  • 第三种:抽象工厂模式, 是23种设计模式之一

简单/静态工厂模式

简单工厂模式的优点

  • 客户端程序不需要关心对象的创建细节,需要哪个对象时只需要向工厂索要即可, 客户端只负责消费,工厂只负责生产, 初步实现了责任的分离

简单工厂模式的缺点

  • 工厂类集中了所有产品的创造逻辑,有人把它叫做上帝类/全能类, 显然工厂类非常关键一旦出问题整个系统将瘫痪
  • 不符合OCP开闭原则,在进行系统产品扩展时需要修改工厂类的代码创建新的产品,这样客户端才能获取到扩展的产品

简单工厂模式的角色包括三个:抽象产品角色,具体产品角色, (静态)工厂类角色(提供创建对象的静态方法)

// 抽象产品角色: 武器
public abstract class Weapon {
    // 所有的武器都有攻击行为
    public abstract void attack();
}
// 具体产品角色:坦克
public class Tank extends Weapon{
    @Override
    public void attack() {
        System.out.println("坦克开炮!");
    }
}
// 具体产品角色:战斗机
public class Fighter extends Weapon{
    @Override
    public void attack() {
        System.out.println("战斗机投下原子弹!");
    }
}
//工厂类角色:根据不同的武器类型不同的生产武器
public class WeaponFactory {
    // 根据不同的武器类型生产不同的武器
    public static Weapon get(String weaponType){
        if (weaponType == null || weaponType.trim().length() == 0) {
            return null;
        }
        Weapon weapon = null;
        if ("TANK".equals(weaponType)) {
            weapon = new Tank();
        } else if ("FIGHTER".equals(weaponType)) {
            weapon = new Fighter();
        } else {
            throw new RuntimeException("不支持该武器!");
        }
        return weapon;
    }
}

编写测试程序,通过指定武器的类型从静态工厂中获取对应的武器

public class Client {
    public static void main(String[] args) {
        Weapon weapon1 = WeaponFactory.get("TANK");
        weapon1.attack();

        Weapon weapon2 = WeaponFactory.get("FIGHTER");
        weapon2.attack();
    }
}

工厂方法模式

工厂方法模式既保留了简单工厂模式的优点,同时又解决了简单工厂模式的缺点

  • 客户端程序不需要关心对象的创建细节,需要哪个对象时只需要向对应的工厂索要即可, 客户端只负责消费,工厂只负责生产
  • 如果想进行产品扩展,只需要添加一个具体产品类和一个具体工厂类,不需要修改原来的代码符合OCP原则

工厂方法模式的缺点

  • 每次增加一个产品时都需要增加一个具体类和对象实现工厂, 使得系统中类的个数成倍增加导致系统的复杂度增加,同时也增加了系统具体类的依赖

工厂方法模式的角色包括:抽象工厂角色(生产多种武器), 具体工厂角色(一个工厂对应生产一种武器), 抽象产品角色, 具体产品角色

//抽象工厂角色: 专门生产各种武器的工厂
public interface WeaponFactory {
    Weapon get();
}
//具体工厂角色:专门生产枪的工厂
public class GunFactory implements WeaponFactory{
    @Override
    public Weapon get() {
        return new Gun();
    }
    
}
//具体工厂角色:专门生成飞机的工厂(工厂也可以通过简单工厂模式封装成一个大工厂,然后调用其的静态方法创建对应的工厂)
public class FighterFactory implements WeaponFactory{
    @Override
    public Weapon get() {
        return new Fighter();
    }
}
// 抽象产品角色: 武器类
public abstract class Weapon {
    // 所有武器都有攻击行为
    public abstract void attack();
}
// 具体产品角色:枪
public class Gun extends Weapon{
    @Override
    public void attack() {
        System.out.println("开枪射击!");
    }
}
// 具体产品角色:战斗机
public class Fighter extends Weapon{
    @Override
    public void attack() {
        System.out.println("战斗机发射核弹!");
    }
}

编写测试程序,获取对应的工厂创建对应的产品

public class Client {
    public static void main(String[] args) {
        // 这里的new GunFactory()可以采用简单工厂模式进行隐藏,调用WeaponFactory的静态方法根据传递的参数创建对应的工厂
        WeaponFactory factory = new GunFactory();
        Weapon weapon = factory.get();
        weapon.attack();

        WeaponFactory factory1 = new FighterFactory();
        Weapon weapon1 = factory1.get();
        weapon1.attack();
    }
}

新增一个匕首产品类只需要新增一个该产品对应的匕首工厂即可

// 具体产品角色:匕首
public class Dagger extends Weapon{
  @Override
  public void attack() {
      System.out.println("切割!");
  }
}
//具体工厂角色:专门生产匕首的工厂
public class DaggerFactory implements WeaponFactory{
  @Override
  public Weapon get() {
      return new Dagger();
  }
}
// 测试生产新增的产品类
public class Client {
  public static void main(String[] args) {
      WeaponFactory factory2 = new DaggerFactory();
      Weapon weapon2 = factory2.get();
      weapon2.attack();
  }
}

抽象工厂模式

工厂方法模式是针对一个产品等级结构(一个产品系列一个工厂类),而抽象工厂模式是针对多个产品等级结构(多个产品系列一个工厂类)

抽象工厂模式的优点

  • 可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象
  • 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象
  • 一个抽象工厂类可以派生出多个具体工厂类,每个具体工厂类可以创建多个具体产品类的实例

抽象工厂模式缺点

  • 产品族扩展非常困难,要增加一个系列的某一产品,既要在AbstractFactory里加代码,又要在具体的里面加代码

在这里插入图片描述

抽象工厂中包含4个角色:抽象工厂角色, 具体工厂角色, 抽象产品角色, 具体产品角色

抽象产品角色:武器产品族,水果产品族

public abstract class Weapon {
    // 所以武器都有攻击行为
    public abstract void attack();
}

public abstract class Fruit {
    // 所有果实都有一个成熟周期
    public abstract void ripeCycle();
}

具体产品角色:武器产品族

// 武器产品族中的产品等级1
public class Gun extends Weapon{
    @Override
    public void attack() {
        System.out.println("开枪射击!");
    }
}

// 武器产品族中的产品等级2
public class Dagger extends Weapon{
    @Override
    public void attack() {
        System.out.println("切割!");
    }
}


// 水果产品族中的产品等级1
public class Orange extends Fruit{
    @Override
    public void ripeCycle() {
        System.out.println("橘子的成熟周期是10个月");
    }
}

package com.powernode.product;

// 水果产品族中的产品等级2 
public class Apple extends Fruit{
    @Override
    public void ripeCycle() {
        System.out.println("苹果的成熟周期是8个月");
    }
}

抽象工厂角色: 既能生产武器又能生产水果

public abstract class AbstractFactory {
    public abstract Weapon getWeapon(String type);
    public abstract Fruit getFruit(String type);
}

具体工厂角色: 武器族工厂, 水果族工厂,根据用户提供的名称创建具体的产品

// 武器族工厂
public class WeaponFactory extends AbstractFactory{
    public Weapon getWeapon(String type){
        if (type == null || type.trim().length() == 0) {
            return null;
        }
        if ("Gun".equals(type)) {
            return new Gun();
        } else if ("Dagger".equals(type)) {
            return new Dagger();
        } else {
            throw new RuntimeException("无法生产该武器");
        }
    }

    @Override
    public Fruit getFruit(String type) {
        return null;
    }
}
// 水果族工厂
public class FruitFactory extends AbstractFactory{
    @Override
    public Weapon getWeapon(String type) {
        return null;
    }

    public Fruit getFruit(String type){
        if (type == null || type.trim().length() == 0) {
            return null;
        }
        if ("Orange".equals(type)) {
            return new Orange();
        } else if ("Apple".equals(type)) {
            return new Apple();
        } else {
            throw new RuntimeException("我家果园不产这种水果");
        }
    }
}

测试程序

public class Client {
    public static void main(String[] args) {
        // 客户端调用方法时只面向AbstractFactory调用方法
        AbstractFactory factory = new WeaponFactory(); 
        Weapon gun = factory.getWeapon("Gun");
        Weapon dagger = factory.getWeapon("Dagger");
        gun.attack();
        dagger.attack();

        AbstractFactory factory1 = new FruitFactory(); 
        Fruit orange = factory1.getFruit("Orange");
        Fruit apple = factory1.getFruit("Apple");
        orange.ripeCycle();
        apple.ripeCycle();
    }
}

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

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

相关文章

Leetcode—234.回文链表【简单】

2023每日刷题(二十七) Leetcode—234.回文链表 直接法实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ bool isPalindrome(struct ListNode* head) {if(head NULL) {return t…

【mysql】CommunicationsException: Communications link failure

CommunicationsException: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. 通信异常:通信链路故障 最后一个成功发送到服务器的数据包是0毫秒前…

华为ensp:ospf末梢stub完全末梢totally Stub

现在宣告都宣告完了,现在要给area1做完全末梢 末梢区域 进入r2系统视图模式 ospf 1area 1 stub quit进入r1系统视图 ospf 1 area 1 stub quit 现在去r1上查看 末梢成功 完全末梢 进入r2系统视图 ospf 1 area 1stub no-summary 现在就成为完全末梢了&…

YOLOv8-Seg改进: 分割小目标系列篇 | 小目标分割到大目标分割一网打尽的GFPN

🚀🚀🚀本文改进:一种新的路径融合GFPN,包含跳层与跨尺度连接,助力YOLOv8-seg Neck,实现创新 🚀🚀🚀GFPN在不同分割场景均有涨点的表现,尤其适合存在不同大小分割尺寸的场景 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,…

计算机毕业设计选题推荐-校园交流平台微信小程序/安卓APP-项目实战

✨作者主页:IT研究室✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

1204. 错误票据

题目: 1204. 错误票据 - AcWing题库 思路: 将输入的数据存入数组,从小到大排序后遍历,若 (a[i] a[i - 1])res1 a[i]--->重号;若(a[i] - a[i - 1] > 2)res2 a[i] - 1--->断号。 难点:题目只告诉我们输入…

【Linux】:静动态库

静动态库 一.静态库1.设计静态库2.生成静态库3.发布静态库4.使用静态库 二.动态库1.设计动态库2.生成和发布动态库3.使用 一.静态库 程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。 静态库链接格式:libxxx.a(前缀是lib,后缀是…

【数字图像处理】RGB 转灰度图

常见的数字图像格式有 RGB, RGBA, YCbCr 等,RGB/RGBA 格式适合存储,而 YCbCr 格式适合图像处理。在数字图像处理中,通常需要将 RGB 格式的图像变换为灰度图,再进行后续的处理,例如边缘检测、锐化等。本文主要介绍数字图…

数据结构 树和二叉树

敬请期待 1. 术语详解 树: 二叉树: 森林: 完全二叉树: 满二叉树: 二叉排序树: 二叉搜索树: 哈夫曼树:分为左小右大和左先右后两种构造方法。 平衡二叉树: 线索…

【Bug】当用opencv库的imread()函数读取图像,用matplotlib库的plt.imshow()函数显示图像时,图像色彩出现偏差问题的解决方法

一,问题描述 我们在利用opencv的imread读取本地图像,进行一系列处理,但是发现用matplotlib库的imshow()函数显示的时候出现色彩改变,比如图像偏黄,偏红,偏蓝等等,但是对…

黑马程序员微服务Docker实用篇

Docker实用篇 0.学习目标 1.初识Docker 1.1.什么是Docker 微服务虽然具备各种各样的优势,但服务的拆分通用给部署带来了很大的麻烦。 分布式系统中,依赖的组件非常多,不同组件之间部署时往往会产生一些冲突。在数百上千台服务中重复部署…

消息队列之初识Rabbit及安装

文章目录 一、MQ的相关概念1.什么是MQ?2.为什么要用MQ2.1流量消峰2.2应用解耦2.3异步处理 3.MQ 的分类3.1.ActiveMQ3.2.Kafka3.3.RocketMQ3.4.RabbitMQ 4.MQ 的选择4.1.Kafka4.2.RocketMQ4.3.RabbitMQ 二、RabbitMQ的相关概念1.四大核心概念2.RabbitMQ 核心部分3.Ra…

面向萌新的技术博客入门指南

Python之禅 在Python的解释器中隐藏一个彩蛋,输入import this就会返回19条Python之禅,具体如下: import this The Zen of Python, by Tim Peters Python之禅 ,by Tim Peters Beautiful is better than ugly. 优美好于丑陋&…

JS算法练习 11.12

leetcode 2622 有时间限制的缓存 看这道题之前,先复习一下Map类的用法(和array.map()区分开) //创建一个Map对象 const map new Map();//set()方法添加键值对 map.set(key, value); map.set(key, {value1, value2})//get()获取键对应的值 …

【 第九章】软件设计师 之 多媒体基础

文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。 备考资料导航 软考好处:软考的…

使用CMake引入第三方so库及头文件并调用头文件声明的函数

首先,要调用别人的so库和头文件,我们自己项目中需要有NDK。 因为只有C++代码才能直接调用C++代码,也就是头文件和so库的函数。 其次,就是要想办法把头文件,so库和项目中的NDK关联起来,然后作为一个整体,生成一个jni,供Java层调用。 最后,二者的关联是通过CMake完成的…

利用爬虫采集外卖数据进行竞争对手分析

目录 一、引言 二、准备工作 三、爬取数据 四、数据处理与存储 五、竞争对手分析 六、结论与展望 一、引言 在当今的数字化时代,数据已经成为企业成功的关键因素之一。对于餐饮外卖行业来说,数据的收集和分析尤为重要。通过对竞争对手的数据进行采…

【hacker送书第一期】嵌入式虚拟化技术与应用

第一期图书推荐 前言为什么嵌入式系统需要虚拟化技术?专家推荐本书适用群体内容简介目录权威作者团队参与方式 前言 随着物联网设备的爆炸式增长和万物互联应用的快速发展,虚拟化技术在嵌入式系统上受到了业界越来越多的关注、重视和实际应用。嵌入式系…

OpenMMlab导出yolov3的onnx模型并推理

手动导出 直接使用脚本 import torch from mmdet.apis import init_detector, inference_detectorconfig_file ./configs/yolo/yolov3_mobilenetv2_8xb24-ms-416-300e_coco.py checkpoint_file yolov3_mobilenetv2_mstrain-416_300e_coco_20210718_010823-f68a07b3.pth mod…

pyTorch Hub 系列#2:VGG 和 ResNet

一、说明 在上一篇教程中,我们了解了 Torch Hub 背后的本质及其概念。然后,我们使用 Torch Hub 的复杂性发布了我们的模型,并通过相同的方式访问它。但是,当我们的工作要求我们利用 Torch Hub 上提供的众多全能模型之一时,会发生什么? 在本教程中,我们将学习如何利用称为…