瑞_23种设计模式_抽象工厂模式

文章目录

    • 1 抽象工厂模式(Abstract Factory Pattern)
      • 1.1 概念
      • 1.2 介绍
      • 1.3 小结
      • 1.4 结构
    • 2 案例一
      • 2.1 需求
      • 2.2 代码实现
    • 3 案例二
      • 3.1 需求
      • 3.2 代码实现
    • 4 总结
      • 4.1 抽象工厂模式优缺点
      • 4.2 抽象工厂模式使用场景
      • 4.3 抽象工厂模式 VS 工厂方法模式
      • 4.4 抽象工厂模式 VS 建造者模式

🙊 前言:本文章为瑞_系列专栏之《23种设计模式》的抽象工厂模式篇。本文中的部分图和概念等资料,来源于博主学习设计模式的相关网站《菜鸟教程 | 设计模式》和《黑马程序员Java设计模式详解》,特此注明。本文中涉及到的软件设计模式的概念、背景、优点、分类、以及UML图的基本知识和设计模式的6大法则等知识,建议阅读 《瑞_23种设计模式_概述》

本系列 - 设计模式 - 链接:《瑞_23种设计模式_概述》

⬇️本系列 - 创建型模式 - 链接🔗

  单例模式:《瑞_23种设计模式_单例模式》
  工厂模式:《瑞_23种设计模式_工厂模式》
  原型模式:《瑞_23种设计模式_原型模式》
抽象工厂模式:《瑞_23种设计模式_抽象工厂模式》
 建造者模式:《瑞_23种设计模式_建造者模式》

⬇️本系列 - 结构型模式 - 链接🔗

  代理模式:《后续更新》
 适配器模式:《后续更新》
 装饰者模式:《后续更新》
  桥接模式:《后续更新》
  外观模式:《后续更新》
  组合模式:《后续更新》
  享元模式:《后续更新》

⬇️本系列 - 行为型模式 - 链接🔗

模板方法模式:《后续更新》
  策略模式:《后续更新》
  命令模式:《后续更新》
 职责链模式:《后续更新》
  状态模式:《后续更新》
 观察者模式:《后续更新》
 中介者模式:《后续更新》
 迭代器模式:《后续更新》
 访问者模式:《后续更新》
 备忘录模式:《后续更新》
 解释器模式:《后续更新》

在这里插入图片描述

1 抽象工厂模式(Abstract Factory Pattern)

1.1 概念

  抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

  在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

  抽象工厂模式提供了一种创建一系列相关或相互依赖对象的接口,而无需指定具体实现类。通过使用抽象工厂模式,可以将客户端与具体产品的创建过程解耦,使得客户端可以通过工厂接口来创建一族产品。

  抽象工厂模式与工厂方法模式不同,工厂方法模式中考虑的是一类产品的生产,这些工厂只生产同种类产品,同种类产品称为同等级产品,也就是说:工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如电器厂既生产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。

1.2 介绍

  • 意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

  • 主要解决:主要解决接口选择的问题。

  • 何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。

  • 如何解决:在一个产品族里面,定义多个产品。

  • 关键代码:在一个工厂里聚合多个同类产品。

  • 应用实例:工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,但有利于说明抽象工厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。

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

  • 缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

  • 使用场景
      1️⃣ QQ 换皮肤,一整套一起换。
      2️⃣ 生成不同操作系统的程序。

  • 注意事项:产品族难扩展,产品等级易扩展。

  抽象工厂模式通常涉及一族相关的产品,每个具体工厂类负责创建该族中的具体产品。客户端通过使用抽象工厂接口来创建产品对象,而不需要直接使用具体产品的实现类。

1.3 小结

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

  抽象工厂模式是工厂方法模式的升级版,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品

  本文要介绍的抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,下图所示横轴是产品等级,也就是同一类产品;纵轴是产品族,也就是同一品牌的产品,同一品牌的产品产自同一个工厂。

在这里插入图片描述

1.4 结构

  抽象工厂模式的主要角色如下:
    1️⃣ 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品。
    2️⃣ 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
    3️⃣ 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
    4️⃣ 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系。

2 案例一

2.1 需求

  现有一家咖啡店,要生产咖啡还要生产甜点,如提拉米苏、抹茶慕斯等,要是按照工厂方法模式,需要定义提拉米苏类、抹茶慕斯类、提拉米苏工厂、抹茶慕斯工厂、甜点工厂类,很容易发生类爆炸情况。其中拿铁咖啡、美式咖啡是一个产品等级,都是咖啡;提拉米苏、抹茶慕斯也是一个产品等级;拿铁咖啡和提拉米苏是同一产品族(也就是都属于意大利风味),美式咖啡和抹茶慕斯是同一产品族(也就是都属于美式风味)。

  这个案例使用抽象工厂模式实现的类图如下:
在这里插入图片描述

2.2 代码实现

抽象工厂(接口)
/**
 * 抽象工厂
 *
 * @author LiaoYuXing-Ray
 **/
public interface DessertFactory {

    // 生产咖啡的功能
    Coffee createCoffee();

    // 生产甜品的功能
    Dessert createDessert();
}
咖啡(抽象类)
/**
 * 咖啡抽象类
 *
 * @author LiaoYuXing-Ray
 **/
public abstract class Coffee {

    public abstract String getName();

    // 加糖
    public void addSugar() {
        System.out.println("加糖");
    }

    // 加奶
    public void addMilk() {
        System.out.println("加奶");
    }
}
甜品(抽象类)
/**
 * 甜品抽象类
 *
 * @author LiaoYuXing-Ray
 **/
public abstract class Dessert {

    public abstract void show();
}
美式风味的甜品工厂(类)
/**
 * 美式风味的甜品工厂
 * - 生产美式咖啡和抹茶慕斯
 *
 * @author LiaoYuXing-Ray
 **/
public class AmericanDessertFactory implements DessertFactory {

    public Coffee createCoffee() {
        return new AmericanCoffee();
    }

    public Dessert createDessert() {
        return new MatchaMousse();
    }
}
意大利风味甜品工厂(类)
/**
 * 意大利风味甜品工厂
 * - 生产拿铁咖啡和提拉米苏甜品
 *
 * @author LiaoYuXing-Ray
 **/
public class ItalyDessertFactory implements DessertFactory {

    public Coffee createCoffee() {
        return new LatteCoffee();
    }

    public Dessert createDessert() {
        return new Tiramisu();
    }
}
美式咖啡(类)
/**
 * 美式咖啡
 *
 * @author LiaoYuXing-Ray
 **/
public class AmericanCoffee extends Coffee {

    public String getName() {
        return "美式咖啡";
    }
}
拿铁咖啡(类)
/**
 * 拿铁咖啡
 *
 * @author LiaoYuXing-Ray
 **/
public class LatteCoffee extends Coffee {

    public String getName() {
        return "拿铁咖啡";
    }
}
抹茶慕斯(类)
/**
 * 抹茶慕斯类
 *
 * @author LiaoYuXing-Ray
 **/
public class MatchaMousse extends Dessert {
    @Override
    public void show() {
        System.out.println("抹茶慕斯");
    }
}
提拉米苏(类)
/**
 * 提拉米苏类
 *
 * @author LiaoYuXing-Ray
 **/
public class Tiramisu extends Dessert {
    @Override
    public void show() {
        System.out.println("提拉米苏");
    }
}
测试类
/**
 * 测试类
 *
 * @author LiaoYuXing-Ray
 **/
public class Client {
    public static void main(String[] args) {
        // 创建的是意大利风味甜品工厂对象
//         ItalyDessertFactory factory = new ItalyDessertFactory();
        AmericanDessertFactory factory = new AmericanDessertFactory();
        // 获取拿铁咖啡和提拉米苏甜品
        Coffee coffee = factory.createCoffee();
        Dessert dessert = factory.createDessert();

        System.out.println(coffee.getName());
        dessert.show();
    }
}

瑞:该案例实现使用抽象工厂模式,如果要加同一个产品族的话,只需要再加一个对应的工厂类即可,不需要修改其他的类。

3 案例二

本案例为菜鸟教程中的案例

3.1 需求

  我们将创建 Shape 和 Color 接口和实现这些接口的实体类。下一步是创建抽象工厂类 AbstractFactory。接着定义工厂类 ShapeFactory 和 ColorFactory,这两个工厂类都是扩展了 AbstractFactory。然后创建一个工厂创造器/生成器类 FactoryProducer。

  AbstractFactoryPatternDemo 类使用 FactoryProducer 来获取 AbstractFactory 对象。它将向 AbstractFactory 传递形状信息 Shape(CIRCLE / RECTANGLE / SQUARE),以便获取它所需对象的类型。同时它还向 AbstractFactory 传递颜色信息 Color(RED / GREEN / BLUE),以便获取它所需对象的类型。

  类图如下:

在这里插入图片描述

3.2 代码实现

步骤1
  为形状创建一个接口。

Shape.java
public interface Shape {
   void draw();
}

步骤2
  创建实现接口的实体类。

Rectangle.java
public class Rectangle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}
Square.java
public class Square implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}
Circle.java
public class Circle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}

步骤3
  为颜色创建一个接口。

Color.java
public interface Color {
   void fill();
}

步骤4

  创建实现接口的实体类。

Red.java
public class Red implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Red::fill() method.");
   }
}
Green.java
public class Green implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Green::fill() method.");
   }
}
Blue.java
public class Blue implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Blue::fill() method.");
   }
}

步骤5
  为 Color 和 Shape 对象创建抽象类来获取工厂。

AbstractFactory.java
public abstract class AbstractFactory {
   public abstract Color getColor(String color);
   public abstract Shape getShape(String shape);
}

步骤6
  创建扩展了 AbstractFactory 的工厂类,基于给定的信息生成实体类的对象。

ShapeFactory.java
public class ShapeFactory extends AbstractFactory {
    
   @Override
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }        
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
   
   @Override
   public Color getColor(String color) {
      return null;
   }
}
ColorFactory.java
public class ColorFactory extends AbstractFactory {
    
   @Override
   public Shape getShape(String shapeType){
      return null;
   }
   
   @Override
   public Color getColor(String color) {
      if(color == null){
         return null;
      }        
      if(color.equalsIgnoreCase("RED")){
         return new Red();
      } else if(color.equalsIgnoreCase("GREEN")){
         return new Green();
      } else if(color.equalsIgnoreCase("BLUE")){
         return new Blue();
      }
      return null;
   }
}

步骤7
  创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂。

FactoryProducer.java
public class FactoryProducer {
   public static AbstractFactory getFactory(String choice){
      if(choice.equalsIgnoreCase("SHAPE")){
         return new ShapeFactory();
      } else if(choice.equalsIgnoreCase("COLOR")){
         return new ColorFactory();
      }
      return null;
   }
}

步骤8
  使用 FactoryProducer 来获取 AbstractFactory,通过传递类型信息来获取实体类的对象。

AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo {
   public static void main(String[] args) {
 
      //获取形状工厂
      AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
 
      //获取形状为 Circle 的对象
      Shape shape1 = shapeFactory.getShape("CIRCLE");
 
      //调用 Circle 的 draw 方法
      shape1.draw();
 
      //获取形状为 Rectangle 的对象
      Shape shape2 = shapeFactory.getShape("RECTANGLE");
 
      //调用 Rectangle 的 draw 方法
      shape2.draw();
      
      //获取形状为 Square 的对象
      Shape shape3 = shapeFactory.getShape("SQUARE");
 
      //调用 Square 的 draw 方法
      shape3.draw();
 
      //获取颜色工厂
      AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
 
      //获取颜色为 Red 的对象
      Color color1 = colorFactory.getColor("RED");
 
      //调用 Red 的 fill 方法
      color1.fill();
 
      //获取颜色为 Green 的对象
      Color color2 = colorFactory.getColor("GREEN");
 
      //调用 Green 的 fill 方法
      color2.fill();
 
      //获取颜色为 Blue 的对象
      Color color3 = colorFactory.getColor("BLUE");
 
      //调用 Blue 的 fill 方法
      color3.fill();
   }
}

步骤9
  执行程序,输出结果:

	Inside Circle::draw() method.
	Inside Rectangle::draw() method.
	Inside Square::draw() method.
	Inside Red::fill() method.
	Inside Green::fill() method.
	Inside Blue::fill() method.

4 总结

4.1 抽象工厂模式优缺点

  • 优点
      1️⃣ 解耦:抽象工厂模式有助于降低客户端与具体实现之间的耦合度,从而提高系统的可扩展性和可维护性。
      2️⃣ 灵活性:抽象工厂模式使得系统更加灵活,可以轻松地添加或删除产品族,而无需修改客户端代码。
      3️⃣ 易于测试:由于具体实现与客户端代码的解耦,使得测试变得更加容易,可以更容易地模拟和验证各种不同的工厂实现。
      4️⃣ 多等级产品:抽象工厂模式可以支持多等级的产品,每个等级可以有自己的工厂实现,从而实现更细粒度的控制和配置。

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

  • 缺点
      1️⃣ 代码复杂度增加:使用抽象工厂模式需要编写更多的代码和接口,这可能会增加代码的复杂度和开发时间。
      2️⃣ 违反开闭原则:在抽象工厂模式中,如果要添加一个新的产品族,需要修改抽象工厂接口及其所有子类,这违反了开闭原则(即软件实体应该对扩展开放,对修改封闭)。
      3️⃣ 过度抽象:抽象工厂模式可能会导致过度抽象,使得系统变得更加复杂和难以理解。
      4️⃣ 具体实现依赖:如果具体实现依赖于抽象工厂,那么它们之间的耦合度仍然很高,这可能会限制系统的灵活性和可维护性。

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

4.2 抽象工厂模式使用场景

  • 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
  • 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
  • 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

  如:输入法换皮肤,一整套一起换。生成不同操作系统的程序。

4.3 抽象工厂模式 VS 工厂方法模式

  抽象工厂模式是工厂方法模式的升级版,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

4.4 抽象工厂模式 VS 建造者模式

  抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式则是不需要关心构建过程,只关心什么产品由什么工厂生产即可。

  建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品。

  如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车。




本文是博主的粗浅理解,可能存在一些错误或不完善之处,如有遗漏或错误欢迎各位补充,谢谢

  如果觉得这篇文章对您有所帮助的话,请动动小手点波关注💗,你的点赞👍收藏⭐️转发🔗评论📝都是对博主最好的支持~


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

记一次生产系统每隔10小时(36000000毫秒)固定进行一次Full GC排查思路

一、 背景描述 某个应用在生产环境通过系统监控发现,应用每隔10小时就会触发一次Full GC,该系统当时承接的业务量并不大,而且固定10小时就会进行Full GC,通过监控时间轴发现Full GC频率很规律,直觉告诉我这不是JVM自身…

回归预测 | Matlab实现RIME-CNN-LSTM-Attention霜冰优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制)

回归预测 | Matlab实现RIME-CNN-LSTM-Attention霜冰优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制) 目录 回归预测 | Matlab实现RIME-CNN-LSTM-Attention霜冰优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制&#xff0…

计算机网络-差错控制(奇偶校验码 CRC循环冗余码)

文章目录 差错从何而来从传感器层面提高信道比来减少线路本身的随机噪声的一个例子热噪声和冲击噪声 数据链路层的差错控制检错编码-奇偶校验码检错编码-CRC循环冗余码例子注意 差错从何而来 噪声通常指的是任何未预期的、随机的信号干扰,这些干扰可能源自多种物理…

Python脚本自动去除文档中无用的信息

1.在进行嵌入式开发过程中会遇到此类情况: 想去掉文档中的“//0x20”的信息,手动消除的话会很麻烦,这时用python脚本就很方便。 2.源码: #!/usr/bin/python3# 打开一个文件 f open("test.txt", "r")text …

LabVIEW智能温度直流模件自动测试系统

LabVIEW智能温度直流模件自动测试系统 自动化测试系统在提高测试效率和准确性方面发挥着越来越重要的作用。介绍了一种基于LabVIEW的智能温度直流模件(TDCA)自动测试系统的设计与实施,旨在提高测控装置的产品质量。 系统的硬件平台主要由PS…

【Boost】:searcher的建立(四)

searcher的建立 一.初始化二.搜索功能三.完整源代码 sercher主要分为两部分:初始化和查找。 一.初始化 初始化分为两步:1.创建Index对象;2.建立索引 二.搜索功能 搜索分为四个步骤 分词;触发:根据分词找到对应的文档…

P4071 [SDOI2016] 排列计数 错排,递归公式

错排公式理解: //f(x)表示1~x的错排数目 // //1选择(x-1种) //乘以剩下的总数目就是答案。//(1选了2就接着排2了,这样所有的都可以算到,是递归所以难想)// 选2时 // 2可选 1 和 3~x//2选1,对2开始来说此次总数就是1*f(…

Linux权限【超详细】

📙 作者简介 :RO-BERRY 📗 学习方向:致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持 目录 扩展知识&#xff1a…

C++项目 -- 高并发内存池(二)Thread Cache

C项目 – 高并发内存池(二)Thread Cache 文章目录 C项目 -- 高并发内存池(二)Thread Cache一、高并发内存池整体框架设计二、thread cache设计1.整体设计2.thread cache哈希桶映射规则3.TLS无锁访问4.thread cache代码 一、高并发…

【数据分享】1米分辨率土地覆盖数据集SinoLC-1

数据链接 SinoLC-1: the first 1-meter resolution national-scale land-cover map of China created with the deep learning framework and open-access data (Update data: August, 2023) (zenodo.org)https://zenodo.org/records/8214467 数据分享 数据分享到了公众号&…

2024/2/4

一.选择题 1、下列不能作为类的成员的是(B) A. 自身类对象的指针 B. 自身类对象 C. 自身类对象的引用 D. 另一个类的对象 2、假定AA为一个类,a()为该类公有的函数成员,x为该类的一个对象,则访问x对象中…

你今年过年回去吗?

#过年 我是一名21岁刚毕业的大学生,专业是软件技术,主修c#,之前在上海实习了一年,正式工作后来到了深圳,进入了一家电商公司实习。至于我为什么转行了,大家懂的都懂 现在是20240203晚上19.39,还…

WordPress Plugin HTML5 Video Player SQL注入漏洞复现(CVE-2024-1061)

0x01 产品简介 WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是一个应用插件。 0x02 漏洞概述 WordPress Plugin HTML5 Video Player 插件 get_v…

2024美赛数学建模F题思路源码

赛题目的 赛题目的: 问题描述: 解题的关键: 问题一. 问题分析 问题解答 问题二. 问题分析 问题解答 问题三. 问题分析 问题解答 问题四. 问题分析 问题解答 问题五. 问题分析 问题解答

华为机考入门python3--(8)牛客8-合并表记录

分类:字典排序 知识点: 将输入转成int的列表 my_list list(map(int, input().strip().split( ))) 将列表转为元组 tuple(my_list) 访问元素为元组的列表 for first, second, third in my_list: 对字典进行排序 sorted(my_dict.items())…

微软Azure-OpenAI 测试调用及说明

本文是公司在调研如何集成Azure-openAI时,调试测试用例得出的原文,原文主要基于官方说明文档简要整理实现 本文已假定阅读者申请部署了模型,已获取到所需的密钥和终结点 变量名称值ENDPOINT从 Azure 门户检查资源时,可在“密钥和…

【C语言】static关键字的使用

目录 一、静态本地变量 1.1 静态本地变量的定义 1.2 静态本地变量和非静态本地变量的区别 二、静态函数 2.1 静态函数的定义 2.2 静态函数与非静态函数的区别 三、静态全局变量 3.1 静态全局变量的定义 3.2 静态全局变量和非静态全局变量的区别 四、静态结构体变量 …

【C++入门学习指南】:函数重载提升代码清晰度与灵活性

🎥 屿小夏 : 个人主页 🔥个人专栏 : C入门到进阶 🌄 莫道桑榆晚,为霞尚满天! 文章目录 📑前言一、函数重载1.1 函数重载的概念1.2 函数重载的作用1.3 C支持函数重载的原理1.4 扩展 &…

寒假作业-day3

1>请编程实现双向链表的头插&#xff0c;头删、尾插、尾删 请编程实现双向链表按任意位置插入、删除、修改、查找 代码&#xff1a; #include<stdio.h> #include<stdlib.h> #include<string.h>typedef int datatype; typedef struct Node{datatype data…

PHP入门指南:起步篇

PHP入门指南&#xff1a;起步篇 PHP入门指南&#xff1a;起步篇什么是PHP&#xff1f;PHP 的优点PHP 开发环境搭建选择本地服务器软件包安装PHP环境配置Web服务器和PHP测试PHP安装 第一个PHP脚本PHP基础语法标记注释变量数据类型常量条件语句循环函数 PHP入门指南&#xff1a;起…