当前位置: 首页 > news >正文

学习设计模式《五》——工厂方法模式

一、基础概念

        工厂方法模式的本质是【延迟到子类来选择实现】;

        工厂方法模式的定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类,FactoryMethod使一个类的实例化延迟到其子类 。

工厂方法模式的功能
序号说明
0工厂方法模式功能:是指让父类在不知道具体实现的情况下,完成自身的功能调用;而具体的实现延迟到子类来实现
1通常父类会是一个抽象类,里面包含创建所需对象的抽象方法,这些抽象方法就是工厂方法注意:子类在实现这些抽象方法的时候,通常并不是真正地由子类来实现具体的功能,
  而是在子类的方法里面做选择,选择具体的产品实现对象
2实现成具体的类(通常情况下需要具体的子类来决定要如何创建父类所需要的对象; 通过工厂方法,可以让子类对象来覆盖父类的实现,从而提供更好的灵活性)
3工厂方法的参数和返回(工厂方法的实现中,可能需要参数,以便决定到底选用哪一种具体的实现;  一般工厂方法返回的是被创建对象的接口对象,当然也可以是抽象类或者一个具体类的实例)
4谁来使用工厂方法创建对象(应该是Creator中的其他方法在使用工厂方法创建对象;客户端在使用Creator对象)
如何理解IOC/DI【IOC---InversionofControl 控制反转】【DI---Dependency Injection 依赖注入】
序号说明
1参与者都有谁?(一般有三方参与者:一个是某个对象(任意的普通对象);另一个是IOC/DI的容器(指用来实现IOC/DI功能的一个框架程序);最后一个是某个对象的外部资源)
2谁依赖于谁:当然是某个对象依赖于IOC/DI的容器
3为什么需要依赖:对象需要IOC/DI的容器来提供对象需要的外部资源
4谁注入于谁:IOC/DI的容器注入控制对象;
5到底注入什么:注入某个对象所需要的外部资源
6谁控制谁:当然是IOC/DI的容器来控制对象了
7控制什么:主要是控制对象实例的创建
8

为何叫反转:反转是相对于正向而言的,那什么算是正向的呢?(常规情况下的应用程序:

  如果A里面要使用C,你会怎么做?当然是直接创建C的对象【这种情况就被称为正向的】;
【那什么是反向呢?就是A类中不再主动获取C,而是被动的等待,等待IOC/DI的容器获取一个C的实例, 然后反向地注入到A类中】)

9依赖注入和控制反转是同一概念吗?(依赖注入和控制反转是对同一件事情的不同描述;
【依赖注入】是从应用程序的角度描述,即【应用程序依赖容器创建并注入它所需要的外部资源】;
【控制反转】是从容器的角度描述,即【容器控制应用程序,由容器反向地向应用程序注入其所需的外部资源】)
10工厂方法与IOC/DI的关系【工厂方法与IOC/DI的思想是相似的,都是主动变被动,进行了主从换位,从而获得了更灵活的程序结构】
工厂模式的优缺点
序号工厂模式的优点工厂模式的缺点
1

可以在不知具体实现的情况下编程

(若需要某个产品对象,只需要使用接口即可,无需关心具体实现,具体实现延迟到子类完成)

具体产品对象与工厂方法的耦合性(在工厂方法模式中,工厂方法是需要创建具体产品对象的实例,因此具体产品对象与工厂方法耦合)
2

更容易扩展对象的新版本

(工厂方法给子类提供了一个挂钩(钩子方法hook),使得扩展新对象版本变得非常容易)

3

连接平行的类层次

(工厂方法除了可以创造产品对象外,在连接平行的类层次上也容易) 

        参数化工厂方法:指通过给工厂方法传递参数,让工厂方法根据参数的不同来创建不同的产品对象

        何时选用工厂方法模式?

                1、如果一个类需要创建某个接口对象,但是又不知道具体的实现,可选择工厂方法模式,把创建对象工作延迟到子类实现;

                 2、如果一个类本身就希望由它的子类来创建所需对象的时候,就使用工厂方法  

二、工厂方法模式示例

        业务需求:实现一个导出数据的应用框架,来让客户选择数据的导出方式,并真正的执行数据导出(通常这种框架系统在导出数据上会有一些约定的方式,如:导出为文本格式、数据库格式、xml格式等)。

需求知识点分析:
        1、框架是什么?框架是能完成一定功能的半成品软件
        2、框架能做什么?能完成一定的功能,加快应用开发进度;给我们一个精良的程序架构
        3、对框架的理解(基于框架的开发,事情还是那些事情,这是看谁做的问题;虽然基于框架开发, 可以不去做框架所做的事情,但是应该明白框架在做什么,以及框架是如何实现相应功能的);

      4、框架和设计模式的关系:

                  《1》设计模式比框架更抽象(框架是已经实现出来的软件了,虽是半成品,但是已经实现了;但设计模式的重心是在解决问题的方案上,即思想层面);

                  《2》设计模式是比框架更小的体系结构元素(框架的目标很明确,就是要解决某个领域的某些问题,是很具体的功能;不同领域实现出来的框架不一样);

                  《3》框架比设计模式更加特例化(框架总是针对特定领域;  设计模式更加注重从思想是哪个、方法上解决问题,更加通用化);

 问题分析:

         1、需要实现导出数据的应用框架(即不管用户选择什么样的导出格式,最后打出的都是对应的文件;且系统并不知道究竟要导出成为什么样的文件;因此应该有一个统一的接口来描述系统最后生成的对象, 并操作输出的文件) 【所以第一步就是设计一个导出文件的接口并定义导出方法】  。               

         2、对于实现导出数据的业务功能对象,它应该根据需要来创建相应的导出接口实现对象,因此特定的导出实现与具体的业务相关的;但是对于实现导出数据的业务功能对象来说,它并不知道应该创建哪一个导出接口对象, 也不知道如何创建【即:对于实现导出数据业务的对象,它需要创建导出接口的具体对象,但它只知道导出接口却不知道其具体的实现,此时应该怎么办?】。

 2.1、典型的工厂方法示例 

1、定义一个导出内容的接口

/***
*	Title:"设计模式" 项目
*		主题:工厂方法
*	Description:
*	    业务需求:实现一个导出数据的应用框架,来让客户选择数据的导出方式,并真正的执行数据导出
*	                (通常这种框架系统在导出数据上会有一些约定的方式,如:导出为文本格式、数据库格式、xml格式等)
*	              
*	    需求知识点分析:
*	            1、框架是什么?(框架是能完成一定功能的半成品软件)
*	            2、框架能做什么?(能完成一定的功能,加快应用开发进度;给我们一个精良的程序架构)
*	            3、对框架的理解(基于框架的开发,事情还是那些事情,这是看谁做的问题;虽然基于框架开发,
*	                            可以不去做框架所做的事情,但是应该明白框架在做什么,以及框架是如何实现相应功能的)
*	            
*	            4、框架和设计模式的关系:
*	                《1》设计模式比框架更抽象(框架是已经实现出来的软件了,虽是半成品,但是已经实现了;但设计模式的重心是在解决问题的方案上,即思想层面)
*	                《2》设计模式是比框架更小的体系结构元素(框架的目标很明确,就是要解决某个领域的某些问题,是很具体的功能;不同领域实现出来的框架不一样)
*	                《3》框架比设计模式更加特例化(框架总是针对特定领域;  设计模式更加注重从思想是哪个、方法上解决问题,更加通用化)
*	            
*	    问题分析:
*	             1、需要实现导出数据的应用框架(即不管用户选择什么样的导出格式,最后打出的都是对应的文件;
*	               且系统并不知道究竟要导出成为什么样的文件;因此应该有一个统一的接口来描述系统最后生成的对象,
*	               并操作输出的文件) 【所以第一步就是设计一个导出文件的接口并定义导出方法】  
*	             2、对于实现导出数据的业务功能对象,它应该根据需要来创建相应的导出接口实现对象,因此特定的导出实现
*	                与具体的业务相关的;但是对于实现导出数据的业务功能对象来说,它并不知道应该创建哪一个导出接口对象,
*	                也不知道如何创建【即:对于实现导出数据业务的对象,它需要创建导出接口的具体对象,但它只知道导出接口
*	                却不知道其具体的实现,此时应该怎么办?】
*	                   
*	Date:2025
*	Version:0.1版本
*	Author:Coffee
*	Modify Recoder:***/using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern
{/// <summary>/// 导出文件对象的接口/// </summary>internal interface IExportFile{//导出内容为文件bool Export(string data);}//Interface_end
}

2、继承导出内容接口实现具体的导出文件类 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern
{/// <summary>/// 导出为文本格式的对象/// </summary>internal class ExportTxtFile : IExportFile{public bool Export(string data){//简单示意Console.WriteLine($"导出【{data}】数据到文本文件");return true;}}//Class_end
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern
{/// <summary>/// 导出为数据库格式的对象/// </summary>internal class ExportDB : IExportFile{public bool Export(string data){//简单示意Console.WriteLine($"导出【{data}】数据到数据库中");return true;}}//Class_end
}

3、实现导出操作类

/***
*	Title:"设计模式" 项目
*		主题:工厂方法模式
*	Description:
*	    基础概念:工厂方法模式的本质是【延迟到子类来选择实现】
*	    工厂方法模式定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类,FactoryMethod使一个类的实例化延迟到其子类
*	                   
*	    工厂方法模式的功能:是让父类在不知道具体实现的情况下,完成自身的功能调用;而具体的实现延迟到子类来实现;
*	            1、通常父类会是一个抽象类,里面包含创建所需对象的抽象方法,这些抽象方法就是工厂方法
*	                (注意:子类在实现这些抽象方法的时候,通常并不是真正地由子类来实现具体的功能,
*	                而是在子类的方法里面做选择,选择具体的产品实现对象)
*	            2、实现成具体的类(通常情况下需要具体的子类来决定要如何创建父类所需要的对象;
*	                通过工厂方法,可以让子类对象来覆盖父类的实现,从而提供更好的灵活性)
*	            3、工厂方法的参数和返回(工厂方法的实现中,可能需要参数,以便决定到底选用哪一种具体的实现;
*	                一般工厂方法返回的是被创建对象的接口对象,当然也可以是抽象类或者一个具体类的实例)
*	            4、谁来使用工厂方法创建对象(应该是Creator中的其他方法在使用工厂方法创建对象;客户端在使用Creator对象)    
*	    
*	    如何理解IOC/DI?【IOC---InversionofControl 控制反转】【DI---Dependency Injection 依赖注入】
*	            1、参与者都有谁?(一般有三方参与者:一个是某个对象(任意的普通对象);另一个是IOC/DI的容器
*	            (指用来实现IOC/DI功能的一个框架程序);最后一个是某个对象的外部资源)
*	            2、谁依赖于谁:当然是某个对象依赖于IOC/DI的容器
*	            3、为什么需要依赖:对象需要IOC/DI的容器来提供对象需要的外部资源
*	            4、谁注入于谁:IOC/DI的容器注入控制对象;
*	            5、到底注入什么:注入某个对象所需要的外部资源
*	            6、谁控制谁:当然是IOC/DI的容器来控制对象了
*	            7、控制什么:主要是控制对象实例的创建
*	            8、为何叫反转:反转是相对于正向而言的,那什么算是正向的呢?(常规情况下的应用程序:
*	                    如果A里面要使用C,你会怎么做?当然是直接创建C的对象【这种情况就被称为正向的】
*	                    【那什么是反向呢?就是A类中不再主动获取C,而是被动的等待,等待IOC/DI的容器获取一个C的实例,
*	                    然后反向地注入到A类中】)
*	            9、依赖注入和控制反转是同一概念吗?(依赖注入和控制反转是对同一件事情的不同描述;
*	                【依赖注入】是从应用程序的角度描述,即【应用程序依赖容器创建并注入它所需要的外部资源】
*	                【控制反转】是从容器的角度描述,即【容器控制应用程序,由容器反向地向应用程序注入其所需的外部资源】)
*	            10、工厂方法与IOC/DI的关系【工厂方法与IOC/DI的思想是相似的,都是主动变被动,进行了主从换位,从而获得了更灵活的程序结构】
*	     
*	     参数化工厂方法:指通过给工厂方法传递参数,让工厂方法根据参数的不同来创建不同的产品对象
*	     
*	     工厂方法模式的优点:
*	            1、可以在不知具体实现的情况下编程(若需要某个产品对象,只需要使用接口即可,无需关心具体实现,具体实现延迟到子类完成)
*	            2、更容易扩展对象的新版本(工厂方法给子类提供了一个挂钩(钩子方法hook),使得扩展新对象版本变得非常容易) 
*	            3、连接平行的类层次(工厂方法除了可以创造产品对象外,在连接平行的类层次上也容易) 
*	            
*	     工厂方法的缺点:
*	            1、具体产品对象与工厂方法的耦合性(在工厂方法模式中,工厂方法是需要创建具体产品对象的实例,因此具体产品对象与工厂方法耦合)
*	             
*	     何时选用工厂方法模式:
*	            1、如果一个类需要创建某个接口对象,但是又不知道具体的实现,可选择工厂方法模式,把创建对象工作延迟到子类实现;
*	            2、如果一个类本身就希望由它的子类来创建所需对象的时候,就使用工厂方法
*	             
*	Date:2025
*	Version:0.1版本
*	Author:Coffee
*	Modify Recoder:***/using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern
{/// <summary>/// 实现导出数据的业务功能对象/// </summary>abstract class ExportOperate{//工厂方法,创建导出的接口对象protected abstract IExportFile FactoryMethod();//导出文件public bool Export(string data){//使用工厂方法IExportFile exportFile = FactoryMethod();return exportFile.Export(data);}}//Class_end
}

4、创建导出操作类的具体实现类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern
{/// <summary>/// 具体的创建器实现对象,实现导出成本文本对象/// </summary>internal class ExportTxtFileOperate : ExportOperate{protected override IExportFile FactoryMethod(){//创建导出为文本的对象return new ExportTxtFile();}}//Class_end
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern
{/// <summary>/// 具体的创建器实现对象,实现创建导出数据库对象/// </summary>internal class ExportDBOperate : ExportOperate{protected override IExportFile FactoryMethod(){//创建导出数据库对象return new ExportDB();}}//Class_end
}

5、客户端调用工厂方法测试

namespace FactoryMethodPattern
{internal class Program{static void Main(string[] args){FactoryMethodTest();Console.ReadLine();}private static void FactoryMethodTest(){Console.WriteLine("------工厂方法测试------");//创建需要使用的对象ExportOperate exportOperate = new ExportTxtFileOperate(); ;//调用导出方法exportOperate.Export("测试导出数据到文本文件");ExportOperate exportOperate2 =new ExportDBOperate();exportOperate2.Export("测试导出数据到数据库");}}//Class_end
}

运行结果如下:

 2.2、IOC/DI与工厂方法示例

定义消息通知的接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern.IOC_DI_Demo
{internal interface IC{void Notify(string info);}//Interface_end
}

  2.2.1、IOC/DI示例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern.IOC_DI_Demo
{/// <summary>/// 我们需要再类A里面使用C,正常情况下我们是直接创建C的实例使用;/// 但我们让类A不在主动获取C,而是被动等待IOC/DI的容器获取一个C的实例,在注入到A类中/// </summary>internal class ClassA{//定义IC,但不实例化创建,等待被注入private IC c = null;public ClassA(IC c){//在这里等待IC对象实例的注入this.c = c;}public void Test(string info){//这里需要使用IC,但是并不主动实例化创建IC,直接从外部获取c.Notify(info);}}//Class_end
}

  2.2.2、工厂方法实现IOC/DI示例

1、创建具体类实现IC接口

using FactoryMethodPattern.IOC_DI_Demo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern.FactoryMethodDemo
{/// <summary>/// 具体实现IC接口的报警类/// </summary>internal class Alarm : IC{public void Notify(string info){Console.WriteLine($"具体实现接口方法的C1类对象,内容是【{info}】");}}//Class_end
}

2、定义抽象方法作为接口操作(也就是工厂方法)

using FactoryMethodPattern.IOC_DI_Demo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern.FactoryMethodDemo
{abstract class ICOperate{//定义一个抽象方法作为工厂protected abstract IC CreateC();//这里需要使用C,但是不知道用哪一个,就不主动创建C了,直接使用,然后让子类实现,客户端选择public void MSGNotify(string info){CreateC().Notify(info);}}//Class_end
}

 3、继承工厂方法的具体实现操作类

using FactoryMethodPattern.IOC_DI_Demo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern.FactoryMethodDemo
{internal class AlarmMSGOpearte : ICOperate{protected override IC CreateC(){//直接在具体的报警消息操作里面使用对应的对象return new Alarm();}}//Class_end
}

4、客户端调用实现IOC/DI示例的测试工厂方法Demo

using FactoryMethodPattern.FactoryMethodDemo;namespace FactoryMethodPattern
{internal class Program{static void Main(string[] args){FactoryMethodDemoTest();Console.ReadLine();}private static void FactoryMethodDemoTest(){//直接使用C操作类实例化了具体的报警消息操作对象类ICOperate cOperate = new AlarmMSGOpearte();//调用消息通知方法cOperate.MSGNotify("测试消息");}}//Class_end
}

    运行结果如下:

  2.3、参数化工厂方法

 1、关于接口【IExportFile】与导出文本文件(ExportTxtFile)、数据库文件(ExportDB)内容都一样不变。

 2、定义参数化工厂的操作方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern
{internal class ParameterExportOperate{/// <summary>/// 导出文件/// </summary>/// <param name="type">对象导出的类型</param>/// <param name="data">需要保存的数据</param>/// <returns>true:表示导出成功</returns>public bool Export(int type,string data){IExportFile exportFile = FactoryMethod(type);return exportFile.Export(data);}/// <summary>/// 工厂方法,创建导出内容的接口对象/// </summary>/// <param name="type">对象导出类型</param>/// <returns></returns>protected virtual IExportFile FactoryMethod(int type){IExportFile exportFile = null;switch (type){case 1:exportFile = new ExportTxtFile();break;case 2:exportFile = new ExportDB();break;default:break;}return exportFile;}}//Class_end
}

 客户端调用该参数化工厂方法

using FactoryMethodPattern.FactoryMethodDemo;namespace FactoryMethodPattern
{internal class Program{static void Main(string[] args){ParameterFactoryMethodTest();Console.ReadLine();}private static void ParameterFactoryMethodTest(){Console.WriteLine("------参数化工厂方法测试------");//创建需使用的对象ParameterExportOperate parameterExportOperate = new ParameterExportOperate();//调用出书数据的功能方法parameterExportOperate.Export(1,"测试数据内容");parameterExportOperate.Export(2, "测试数据内容");}}//Class_end
}

运行结果如下:


3、扩展参数化工厂方法十分容易

《1》新增一个导出XML文件的方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern
{/// <summary>/// 导出为Xml格式的对象/// </summary>internal class ExportXml : IExportFile{public bool Export(string data){//简单示意Console.WriteLine($"导出【{data}】数据到XML文件中");return true;}}//Class_end
}

《2》定义一个类来拓展参数化导出操作类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FactoryMethodPattern
{internal class ExtandParameterExportOperate:ParameterExportOperate{protected override IExportFile FactoryMethod(int type){IExportFile exportFile = null;//可以全部覆盖重写,也可以直接添加类型实现拓展if (type == 3){exportFile = new ExportXml();}else{exportFile=base.FactoryMethod(type);}return exportFile;}}//Class_end
}

客户端调用该扩展的参数化工厂方法测试

using FactoryMethodPattern.FactoryMethodDemo;namespace FactoryMethodPattern
{internal class Program{static void Main(string[] args){ParameterFactoryMethodTest();Console.ReadLine();}private static void ParameterFactoryMethodTest(){Console.WriteLine("------参数化工厂方法测试------");//创建需使用的对象ParameterExportOperate parameterExportOperate = new ParameterExportOperate();//调用出书数据的功能方法parameterExportOperate.Export(1,"测试数据内容");parameterExportOperate.Export(2, "测试数据内容");Console.WriteLine("\n--使用拓展的方法--");ParameterExportOperate extandExportOperate = new ExtandParameterExportOperate();extandExportOperate.Export(1, "测试内容1");extandExportOperate.Export(2, "测试内容2");extandExportOperate.Export(3,"测试内容3");}}//Class_end
}

 运行结果如下:

三、项目源码工程

kafeiweimei/Learning_DesignPattern: 这是一个关于C#语言编写的基础设计模式项目工程,方便学习理解常见的26种设计模式https://github.com/kafeiweimei/Learning_DesignPattern

相关文章:

学习设计模式《五》——工厂方法模式

一、基础概念 工厂方法模式的本质是【延迟到子类来选择实现】&#xff1b; 工厂方法模式的定义&#xff1a;定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类&#xff0c;FactoryMethod使一个类的实例化延迟到其子类 。 工厂方法模式的功能 序号说明0工厂方法模…...

如何将 Azure Active Directory (Azure AD) 作为 SAML IdP 对接到 Keycloak

✅ 一、在 Azure AD 创建 SAML 应用 &#x1f527; 1. 登录 Azure 门户 前往 https://portal.azure.com&#xff0c;使用管理员账号登录。 &#x1f4cc; 2. 创建企业应用&#xff08;Enterprise Application&#xff09; 左侧菜单进入 “企业应用程序”。点击 “新建应用程…...

OCR之身份证识别

前言 OCR身份证识别是光学字符识别技术在身份证领域的应用。通过扫描或拍照获取身份证图像&#xff0c;利用图像处理、深度学习等技术&#xff0c;自动提取姓名、性别、民族、出生日期、地址、身份证号等信息&#xff0c;可大幅提升信息录入效率&#xff0c;广泛应用于政务、金…...

JavaScript 渲染内容爬取:Puppeteer 高级技巧与实践

在现代网络应用中&#xff0c;动态网页内容的爬取一直是开发者面临的挑战之一。Puppeteer 作为一种强大的浏览器自动化工具&#xff0c;为这一问题提供了优雅的解决方案。本文将深入探讨 Puppeteer 的高级技巧&#xff0c;包括动态内容抓取、性能优化、反检测与伪装、复杂自动化…...

组织级项目管理OPM

组织级项目管理(Organizational Project Management, OPM)是一种系统化的管理方法,旨在通过整合项目组合、项目集和项目管理,确保组织的战略目标与项目执行的一致性,提升资源利用效率和项目成功率。以下是其核心内容与框架的详述: 一、组织级项目管理的定义与目标 定义 组…...

HTML与Web 性能优化:构建高速响应的现代网站

HTML 与 Web 性能优化&#xff1a;构建高速响应的现代网站 引言 随着互联网用户对网站加载速度期望的不断提高&#xff0c;前端性能优化已经成为现代 Web 开发的核心竞争力。据 Google 研究表明&#xff0c;页面加载时间每增加 1 秒&#xff0c;用户跳出率就会增加 32%。用户…...

模型 观测者效应

系列文章分享模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。观察即影响&#xff0c;存在因注视而变。 1 观测者效应的应用 1.1 工业心理学—霍桑实验中的生产效率谜题 行业背景&#xff1a;20世纪20年代西方电气公司霍桑工厂&#xff0c;研究者试图通过优化照明…...

Ubuntu启动SMB(Samba)服务步骤

目录 1.基本的Samba服务器搭建流程主要分为四个步骤。 2.Samba工作流程&#xff1a; 3.解读主要配置文件smb.conf 4.开始安装Samba 5.检查Samba服务状态 6.创建Samba共享文件夹 7.配置Samba文件以及设置Samba用户密码 8.重启Samba服务器 9.关闭防火墙 10.Linux客户端…...

使用react的ant-design-pro框架写一个地图组件,可以搜索地图,可以点击地图获取点击的位置及经纬度

首先&#xff0c;先创建一个地图页面&#xff0c;用于显示地图组件&#xff0c;我是在pages文件中创建了一个mapSearch组件。 然后在routes.ts中注册页面。 {path: /mapSearch,name: mapSearch,icon: smile,component: ./mapSearch,}, 第三步就是使用高德地图来创建地图。 关键…...

【每日八股】复习计算机网络 Day4:TCP 协议的其他相关问题

文章目录 昨日内容复习已经建立了 TCP 连接&#xff0c;客户端突然出现故障怎么办&#xff1f;什么时候用长连接&#xff1f;短连接&#xff1f;TCP 的半连接队列与全连接队列&#xff1f;什么是 SYN 攻击&#xff1f;如何避免&#xff1f;TIME_WAIT 的作用&#xff1f;过多如何…...

Git远程操作与标签管理

目录 1.理解分布式版本控制系统 2.远程仓库 3.新建远程仓库 4.克隆远程仓库 5.向远程仓库推送 6.拉取远程仓库 7.配置Git 7.1.忽略特殊文件 7.2.给命令配置别名 8.标签管理 8.1.理解标签 8.2.创建标签 8.3.操作标签 1.理解分布式版本控制系统 Git是目前世界上…...

Element Plus消息通知体系深度解析:从基础到企业级实践

一、核心组件与技术定位 Element Plus的消息通知体系由三个核心组件构成&#xff1a;ElMessage&#xff08;全局提示&#xff09;、ElNotification&#xff08;通知弹窗&#xff09;和ElMessageBox&#xff08;交互式对话框&#xff09;。这套体系的设计目标是为开发者提供轻量…...

SpringCloud组件——Eureka

一.背景 1.问题提出 我们在一个父项目下写了两个子项目&#xff0c;需要两个子项目之间相互调用。我们可以发送HTTP请求来获取我们想要的资源&#xff0c;具体实现的方法有很多&#xff0c;可以用HttpURLConnection、HttpClient、Okhttp、 RestTemplate等。 举个例子&#x…...

[Godot] C#2D平台游戏基础移动和进阶跳跃代码

本文章给大家分享一下如何实现基本的移动和进阶的跳跃&#xff08;跳跃缓冲、可变跳跃、土狼时间&#xff09;以及相对应的重力代码&#xff0c;大家可以根据自己的需要自行修改 实现效果 场景搭建 因为Godot不像Unity&#xff0c;一个节点只能绑定一个脚本&#xff0c;所以我…...

C语言对n进制的处理

先看一道题目: 从键盘获取一个正整数,如果把它转为16进制的数字,那么它是一个几位数呢?如果把它转为28进制又是一个几位数呢? 在讲这个题目之前,我们先要了解进制转换 什么是进制转换&#xff1f; 简单来说&#xff0c;进制就是数位的表示方法。 十进制&#xff08;常用&am…...

rk3568main.cc解析

rk3568main.cc解析 前言解析总结前言 正点原子rk3568学习,rk官方RKNN_MODEL_ZOO文件中 rknn_model_zoo-main/examples/mobilenet/cpp/main.cc 从执行命令:./build-linux.sh -t rk3568 -a aarch64 -d mobilenet 到: cmake ../../examples/mobilenet/cpp \-DTARGET_SOC=rk3…...

【白雪讲堂】[特殊字符]内容战略地图|GEO优化框架下的内容全景布局

&#x1f4cd;内容战略地图&#xff5c;GEO优化框架下的内容全景布局 1️⃣ 顶层目标&#xff1a;GEO优化战略 目标关键词&#xff1a; 被AI理解&#xff08;AEO&#xff09; 被AI优先推荐&#xff08;GEO&#xff09; 在关键场景中被AI复读引用 2️⃣ 三大引擎逻辑&#x…...

S32K144学习(16)-Bootloader

1.什么是bootloader Bootloader&#xff08;引导加载程序&#xff09; 是存储在设备非易失性存储器&#xff08;如 ROM、Flash&#xff09;中的一段特殊程序&#xff0c;负责在设备上电后初始化硬件、加载操作系统&#xff08;OS&#xff09;或用户应用程序&#xff0c;并最终…...

反素数c++

先上代码 #include<bits/stdc.h> using namespace std; typedef long long ll; ll n; ll p[]{2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53}; int maxd,maxval; void dfs(int pl,ll tmp,int num,int up){ if((num>maxd)||(nummaxd&&maxval>tmp)){ …...

C++ linux打包运行方案(cmake)

文章目录 背景动态库打包方案动态库转静态库动态库打到软件包中 运行 背景 使用C编写的一个小项目&#xff0c;需要打包成ubuntu下的可执行文件&#xff0c;方便分发给其他ubuntu执行&#xff0c;因为docker镜像方案过于臃肿&#xff0c;所以需要把项目的动态库都打在软件包中…...

JavaScript 渲染内容爬取实践:Puppeteer 进阶技巧

进一步探讨如何使用 Puppeteer 进行动态网页爬取&#xff0c;特别是如何等待页面元素加载完成、处理无限滚动加载、单页应用的路由变化以及监听接口等常见场景。 一、等待页面元素加载完成 在爬取动态网页时&#xff0c;确保页面元素完全加载是获取完整数据的关键。Puppeteer…...

AI数字人:元宇宙舞台上的闪耀新星(7/10)

摘要&#xff1a;AI数字人作为元宇宙核心角色&#xff0c;提升交互体验&#xff0c;推动内容生产变革&#xff0c;助力产业数字化转型。其应用场景涵盖虚拟社交、智能客服、教育、商业营销等&#xff0c;面临技术瓶颈与行业规范缺失等挑战&#xff0c;未来有望突破技术限制&…...

测试基础笔记第九天

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、数据类型和约束1.数据类型2.约束3.主键4.不为空5.唯一6.默认值 二、数据库操作1.创建数据库2.使用数据库3.修改数据库4.删除数据库和查看所有数据库5.重点&…...

C++抽象基类定义与使用

在 C 中&#xff0c;抽象基类&#xff08;Abstract Base Class, ABC&#xff09; 是一种特殊的类&#xff0c;用于定义接口规范和约束派生类的行为。它通过纯虚函数&#xff08;Pure Virtual Function&#xff09;强制要求派生类实现特定功能&#xff0c;自身不能被实例化。以下…...

20.4 显示数据库数据

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的 20.4.1 设计时进行简单绑定 【例 20.22】【项目&#xff1a;code20-022】设计时关联数据库。 设计时设置DataGridView的DataSource属…...

PyTorch 多 GPU 入门:深入解析 nn.DataParallel 的工作原理与局限

当你发现单个 GPU 已经无法满足你训练庞大模型或处理海量数据的需求时&#xff0c;利用多 GPU 进行并行训练就成了自然的选择。PyTorch 提供了几种实现方式&#xff0c;其中 torch.nn.DataParallel (简称 DP) 因其使用的便捷性&#xff0c;常常是初学者接触多 GPU 训练的第一站…...

UDP协议理解

文章目录 UDP协议理解UDP 协议的特点&#xff1a;UDP协议图示UDP 的头部结构&#xff1a;UDP数据传输图示 UDP 的应用场景&#xff1a;TCP 与UDP对比UDP的传输丢包和顺序错乱问题&#xff08;了解&#xff09;丢包的解决方法&#xff1a;顺序错乱的解决方法&#xff1a;综合应用…...

微信小程序拖拽排序有效果图

效果图 .wxml <view class"container" style"--w:{{w}}px;" wx:if"{{location.length}}"><view class"container-item" wx:for"{{list}}" wx:key"index" data-index"{{index}}"style"--…...

算力网络的早期有关论文——自用笔记

2023年底至2024年初阅读有关论文的自用笔记&#xff0c;作为参考。 算力网络架构 https://baijiahao.baidu.com/s?id1727377583404975414&wfrspider&forpc think&note 是否可以和cpu进程调度联系。 目前&#xff1a;看一些综述深一步了解背景和发展现状,完善认…...

卷积神经网络基础(四)

今天我们继续学习各个激活函数层的实现过程。 目录 5.2 Sigmoid层 六、Affine/Softmax层实现 6.1 Affine层 6.2 批处理版本 5.2 Sigmoid层 sigmoid函数的表达式如下&#xff1a; 用计算图表示的话如下&#xff1a; 计算过程稍微有些复杂&#xff0c;且这里除了乘法和加法…...

【MySQL数据库】表的约束

目录 1&#xff0c;空属性 2&#xff0c;默认值 3&#xff0c;列描述 4&#xff0c;zerofill 5&#xff0c;主键primary key 6&#xff0c;自增长auto_increment 7&#xff0c;唯一键unique 8&#xff0c;外键foreign key 在MySQL中&#xff0c;表的约束是指用于插入的…...

网络威胁情报 | Friday Overtime Trooper

本文将分别从两个环境出发&#xff0c;以实践来体验利用威胁情报分析可疑文件的过程。 Friday Overtime 现在你是一位安全分析人员&#xff0c;正在美美等待周五过去&#xff0c;但就在即将下班之时意外发生了&#xff1a;你的客户发来求助&#xff0c;说他们发现了一些可疑文…...

GPIO(通用输入输出端口)详细介绍

一、基本概念 GPIO&#xff08;General - Purpose Input/Output&#xff09;即通用输入输出端口&#xff0c;是微控制器&#xff08;如 STM32 系列&#xff09;中非常重要的一个外设。它是一种软件可编程的引脚&#xff0c;用户能够通过编程来控制这些引脚的输入或输出状态。在…...

学习笔记——《Java面向对象程序设计》-继承

参考教材&#xff1a; Java面向对象程序设计&#xff08;第3版&#xff09;微课视频版 清华大学出版社 1、定义子类 class 子类名 extends 父类名{...... }如&#xff1a; class Student extends People{...... } &#xff08;1&#xff09;如果一个类的声明中没有extends关…...

基于javaweb的SpringBoot校园失物招领系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...

什么事Nginx,及使用Nginx部署vue项目(非服务器Nginx压缩包版)

什么是 Nginx? Nginx(发音为 “engine-x”)是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。它以其高性能、高并发处理能力和低资源消耗而闻名。以下是 Nginx 的主要特性和用途: 主要特性 高性能和高并发 Nginx 能够处理大量并发连接,适合高…...

nodejs使用require导入npm包,开发依赖和生产依赖 ,全局安装

nodejs使用require导入npm包&#xff0c;开发依赖和生产依赖 &#xff0c;全局安装 ✅ 一、Node.js 中使用 require() 导入 npm 包 // 导入第三方包&#xff08;例如 axios&#xff09; const axios require(axios);// 使用 axios.get(https://api.example.com).then(res &g…...

CSS在线格式化 - 加菲工具

CSS在线格式化 打开网站 加菲工具 选择“CSS在线格式化” 或者直接访问 https://www.orcc.top/tools/css 输入CSS代码&#xff0c;点击左上角的“格式化”按钮 得到格式化后的结果...

图片转base64 - 加菲工具 - 在线转换

图片转base64 - 加菲工具 先进入“加菲工具” 网 打开 https://www.orcc.top&#xff0c; 选择 “图片转base64”功能 选择需要转换的图片 复制 点击“复制”按钮&#xff0c;即可复制转换好的base64编码数据&#xff0c;可以直接用于img标签。...

性能比拼: Redis vs Dragonfly

本内容是对知名性能评测博主 Anton Putra Redis vs Dragonfly Performance (Latency - Throughput - Saturation) 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准 在本视频中&#xff0c;我们将对比 Redis 和 Dragonfly。我们将观察 set 与 get 操作的延迟&#xff…...

如何收集用户白屏/长时间无响应/接口超时问题

想象一下这样的场景:一位用户在午休时间打开某电商应用,准备购买一件心仪已久的商品。然而,页面加载了数秒后依然是一片空白,或者点击“加入购物车”按钮后没有任何反馈,甚至在结算时接口超时导致订单失败。用户的耐心被迅速消耗殆尽,关闭应用,转而选择了竞争对手的产品…...

来啦,烫,查询达梦表占用空间

想象一下oracle&#xff0c;可以查dba_segments&#xff0c;但是这个不可靠&#xff08;达梦官方连说明书都没有&#xff09; 先拼接一个sql set lineshow off SELECT SELECT ||||OWNER|||| AS OWNER,||||TABLE_NAME|||| AS TABLE_NAME,TABLE_USED_SPACE(||||OWNER||||,||||T…...

# 利用迁移学习优化食物分类模型:基于ResNet18的实践

利用迁移学习优化食物分类模型&#xff1a;基于ResNet18的实践 在深度学习的众多应用中&#xff0c;图像分类一直是一个热门且具有挑战性的领域。随着研究的深入&#xff0c;我们发现利用预训练模型进行迁移学习是一种非常有效的策略&#xff0c;可以显著提高模型的性能&#…...

AT24C02芯片简介:小巧强大的串行EEPROM存储器

一、AT24C02概述 AT24C02是一款2K位&#xff08;即256字节&#xff09;的串行EEPROM芯片&#xff0c;采用IC&#xff08;Inter-Integrated Circuit&#xff09;总线进行通信&#xff0c;适合低功耗、小容量存储需求。 主要特性&#xff1a; 项目 参数 存储容量 2Kb&#x…...

【Vue】状态管理(Vuex、Pinia)

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Vue 文章目录 1. 状态管理概述1.1 什么是状态管理1.2 为什么需要状态管理 2. Vuex基础2.1 Vuex核心概念2.1.1 State2.1.2 Getters2.1.3 Mutations2.1.4 Actions2.1.5 Modules 2.2 Vuex辅助函数2.2.1 mapState2.2.2 mapGetters2.…...

施磊老师基于muduo网络库的集群聊天服务器(四)

文章目录 实现登录业务登录业务代码补全数据库接口:查询,更新状态注意学习一下里面用到的数据库api测试与问题**问题1:****问题2:** 用户连接信息与线程安全聊天服务器是长连接服务器如何找到用户B的连接&#xff1f;在业务层存储用户的连接信息多线程安全问题加锁! 处理客户端…...

深度学习-全连接神经网络(过拟合,欠拟合。批量标准化)

七、过拟合与欠拟合 在训练深层神经网络时&#xff0c;由于模型参数较多&#xff0c;在数据量不足时很容易过拟合。而正则化技术主要就是用于防止过拟合&#xff0c;提升模型的泛化能力(对新数据表现良好)和鲁棒性&#xff08;对异常数据表现良好&#xff09;。 1. 概念认知 …...

访问Maven私服的教程

1.首先准备好maven私服的启动器&#xff0c;到bin目录下启动&#xff1a; 2.等待加载&#xff0c;加载过程比较长: 3.访问端口号: 4.仓库简介: 5.在maven的setting中 servers配置信息(设置私服访问的密码): 6.配置私服仓库地址: 7.配置上传地址(私服地址): 8.在自己的副项…...

Linux系统编程 day9 SIGCHLD and 线程

SIGCHLD信号 只要子进程信号发生改变&#xff0c;就会产生SIGCHLD信号。 借助SIGCHLD信号回收子进程 回收子进程只跟父进程有关。如果不使用循环回收多个子进程&#xff0c;会产生多个僵尸进程&#xff0c;原因是因为这个信号不会循环等待。 #include<stdio.h> #incl…...

Linux 内核中 cgroup 子系统 cpuset 是什么?

cpuset 是 Linux 内核中 cgroup&#xff08;控制组&#xff09; 的一个子系统&#xff0c;用于将一组进程&#xff08;或任务&#xff09;绑定到特定的 CPU 核心和 内存节点&#xff08;NUMA 节点&#xff09;上运行。它通过限制进程的 CPU 和内存资源的使用范围&#xff0c;优…...