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

抽象工厂模式:思考与解读

 原文地址:抽象工厂模式:思考与解读  更多内容请关注:

引言

你是否曾经在开发系统时,需要创建一系列相关的对象,而这些对象需要共同协作并保持一致性?假设你有多个不同的产品类型,但它们需要在系统中一起工作。如何确保这些相关产品能够配合得当,同时又不让客户端直接接触到具体的产品类?

如果你正在面临这样的问题,那么你可能会遇到抽象工厂模式。这个模式能够帮助我们封装一系列相关的对象的创建,同时保持对象之间的协调一致性。你是否觉得,这种方法能让系统更容易扩展,同时保持低耦合?

在本文中,我们将通过一系列问题,逐步引导你理解抽象工厂模式的核心概念、实现方式以及适用场景。

什么是抽象工厂模式?

问题1:你如何理解“工厂模式”这一概念?它是否主要用于创建对象?

你可能已经接触过工厂模式,它的核心思想是封装对象的创建逻辑,让客户端不需要直接与具体类打交道。你认为,为什么这种做法能够减少代码的耦合性?它对我们如何组织代码有何帮助?

问题2:如果你有多个产品,且这些产品属于不同的系列或族,你如何设计一个系统来确保这些产品能够配合工作?

假设你在开发一个应用,涉及多个产品系列(如:Windows操作系统下的UI组件、Mac操作系统下的UI组件)。你是否觉得,为了确保这些产品之间能够协调工作,可能需要有一种机制来集中管理这些产品的创建,而不让客户端代码直接操作具体产品类?

抽象工厂模式正是为了解决这个问题而设计的,它允许你创建一系列相关的产品,同时保证每个产品系列之间的兼容性和一致性。

抽象工厂模式的核心概念

问题3:你如何描述抽象工厂模式的结构?它包括哪些核心角色?

抽象工厂模式通常包括以下几个角色:

  1. 抽象工厂(Abstract Factory):声明了创建一系列产品的方法。

  2. 具体工厂(Concrete Factory):实现了抽象工厂声明的创建方法。

  3. 抽象产品(Abstract Product):定义产品的通用接口。

  4. 具体产品(Concrete Product):实现了抽象产品接口。

你是否能理解这种结构如何让系统能够生成不同的产品族,而不暴露具体的产品类?

问题4:在抽象工厂模式中,为什么要有一个“抽象”工厂?它与具体工厂的关系是什么?

抽象工厂类定义了一个接口,允许客户端通过这个接口来创建产品对象,而具体工厂类则负责实现这个接口,生成相应的产品。你是否觉得,这种设计方式能够让客户端与具体产品类解耦,从而提高系统的灵活性和可扩展性?

问题5:抽象工厂模式如何确保产品族的一致性?如果客户端需要不同的产品族,它应该如何选择?

在抽象工厂模式中,每个具体工厂类负责创建某个产品族中的所有产品。你是否理解,为什么每个产品族中的产品要在设计时保持一致性?客户端如何通过选择不同的具体工厂,来使用不同的产品族?

抽象工厂模式的实现

假设你正在开发一个跨平台应用,支持Windows和Mac两种操作系统,并且为每个平台提供不同的UI组件(按钮、窗口等)。我们将使用抽象工厂模式来实现这一需求。

步骤1:定义抽象产品类和具体产品类

from abc import ABC, abstractmethod# 抽象产品:按钮
class Button(ABC):@abstractmethoddef render(self):pass# 抽象产品:窗口
class Window(ABC):@abstractmethoddef open(self):pass# 具体产品:Windows按钮
class WindowsButton(Button):def render(self):print("渲染 Windows 风格的按钮")# 具体产品:Windows窗口
class WindowsWindow(Window):def open(self):print("打开 Windows 风格的窗口")# 具体产品:Mac按钮
class MacButton(Button):def render(self):print("渲染 Mac 风格的按钮")# 具体产品:Mac窗口
class MacWindow(Window):def open(self):print("打开 Mac 风格的窗口")

问题6:为什么要定义抽象产品类(如ButtonWindow)?具体产品类(如WindowsButtonMacButton)又如何与抽象产品类关联?

通过定义抽象产品类,我们能够确保所有具体产品类都遵循相同的接口。这样,客户端可以通过这些接口来操作产品,而不需要关心具体的实现。你是否认为这种做法有助于提高代码的可扩展性和维护性?

步骤2:定义抽象工厂和具体工厂类
# 抽象工厂
class GUIFactory(ABC):@abstractmethoddef create_button(self) -> Button:pass@abstractmethoddef create_window(self) -> Window:pass# 具体工厂:Windows工厂
class WindowsFactory(GUIFactory):def create_button(self) -> Button:return WindowsButton()def create_window(self) -> Window:return WindowsWindow()# 具体工厂:Mac工厂
class MacFactory(GUIFactory):def create_button(self) -> Button:return MacButton()def create_window(self) -> Window:return MacWindow()

问题7:为什么我们要定义一个GUIFactory接口?它与具体工厂类(如WindowsFactoryMacFactory)之间有什么关系?

GUIFactory接口定义了创建一系列产品的方法,而每个具体工厂类则负责实现这些方法,生产相应的产品。你是否认为,这样的设计能够确保同一产品族中的所有产品具有一致性,并且在系统中保持协作?

步骤3:客户端使用工厂
def client_code(factory: GUIFactory):button = factory.create_button()window = factory.create_window()button.render()window.open()if __name__ == "__main__":os_type = input("请输入操作系统(Windows/Mac):")if os_type == "Windows":factory = WindowsFactory()elif os_type == "Mac":factory = MacFactory()else:raise ValueError("未知的操作系统")client_code(factory)

问题8:在客户端代码中,我们如何通过抽象工厂来创建不同的产品族?你是否觉得,这样的设计能让客户端代码更具可扩展性?

通过传入不同的工厂(如WindowsFactoryMacFactory),客户端能够创建相应的产品族,而无需关心具体的产品实现。你认为,这样是否能够让客户端代码专注于功能实现,而不必处理具体类的变化?

抽象工厂模式的优缺点

问题9:抽象工厂模式的优点是什么?它能解决什么问题?

抽象工厂模式通过将产品的创建过程封装到工厂中,能够确保产品族的一致性。你是否理解,为什么它能让系统更加灵活,便于扩展?例如,增加一个新的操作系统产品族时,只需要创建一个新的工厂类,而不需要修改现有的客户端代码。

问题10:抽象工厂模式的缺点是什么?它在某些情况下是否会导致类的数量激增?

抽象工厂模式要求每增加一个产品族,就需要新增一个具体工厂类和一组具体产品类。你认为,这种做法在某些情况下是否会导致系统变得更加复杂,类的数量不断增加?

适用场景

问题11:你能想到哪些场景,抽象工厂模式能够发挥作用?

抽象工厂模式特别适合用于创建多个产品族的系统。例如,跨平台的UI组件、不同数据库类型的连接、不同操作系统下的日志模块等。你能想到其他类似的场景吗?

问题12:在某些情况下,是否有更合适的设计模式来替代抽象工厂模式?例如,当产品的种类非常少时,是否需要这么复杂的模式?

抽象工厂模式适用于产品族多且变化的情况,但如果产品种类较少或不常变化,是否可以选择更简单的工厂方法模式或者简单工厂模式?

接下来,我们将通过具体的代码示例来加深理解抽象工厂模式。

抽象工厂模式深入解读

一、引言

在设计模式中,抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一种创建一系列相关或相互依赖的对象的方式,而无需指定具体的类。换句话说,抽象工厂模式帮助我们创建多个产品对象,而不暴露它们的具体实现。它将对象的创建过程与客户端代码分离,从而减少了代码的耦合度。


二、简单理解:什么是抽象工厂模式?

1. 什么是抽象工厂模式?

抽象工厂模式的核心思想是,通过抽象工厂来创建一系列相关的产品对象。每个具体的工厂类都负责创建某一产品家族中的一组相关产品。抽象工厂本身并不直接创建产品,而是定义了一个接口来指导创建相关产品。

通俗地讲,抽象工厂模式就像是一家生产多个系列产品的工厂,里面有多条生产线,每条生产线负责生产一类产品,而这些产品属于同一个系列。你可以通过选择不同的工厂来获得不同系列的产品。

举个例子:假设你需要创建一个 GUI(图形用户界面)应用程序,你可能需要创建按钮、文本框等多个控件,而这些控件有不同的风格(如Windows风格和Mac风格)。使用抽象工厂模式,你可以创建多个工厂,每个工厂负责创建一个风格系列中的控件。

2. 抽象工厂模式的组成部分

抽象工厂模式通常包含以下几个部分:

  • 抽象工厂(AbstractFactory):定义创建一系列产品的方法。

  • 具体工厂(ConcreteFactory):实现抽象工厂,创建具体的产品。

  • 抽象产品(AbstractProduct):定义产品的接口或抽象类。

  • 具体产品(ConcreteProduct):实现抽象产品接口的具体类,表示某一系列中的具体产品。


三、用自己的话解释:如何理解抽象工厂模式?

1. 类比实际生活中的场景

假设你去一家手机工厂,工厂提供不同的系列:Android系列和iPhone系列。每个系列中会有不同的产品(如手机、耳机、充电器等)。你选择了某一系列,工厂就会根据你的需求生产相关的产品。

在这个场景中,工厂就像是抽象工厂,手机、耳机、充电器等是抽象产品,Android系列和iPhone系列是具体工厂,每个具体工厂负责生产相应系列中的所有产品。

2. 为什么要使用抽象工厂模式?

抽象工厂模式的优势在于,它让你能够以一致的方式创建一系列相关的产品,而无需关心具体的产品细节。它通过创建一系列工厂和产品,确保产品之间的兼容性。例如,你可以选择一个特定的风格系列(如Windows风格的UI控件),然后通过抽象工厂来获取该风格系列中的所有控件。


四、深入理解:抽象工厂模式的实现

接下来,我们通过一个具体的代码示例来实现抽象工厂模式,帮助你更好地理解如何在代码中应用这个模式。

示例:GUI控件工厂

假设我们要开发一个图形用户界面(GUI)应用程序,需要创建不同风格的控件,如按钮、文本框等。我们将使用抽象工厂模式来实现这个场景。

1. 定义抽象产品:按钮和文本框
# 抽象产品:按钮
class Button:def render(self):pass# 抽象产品:文本框
class TextBox:def render(self):pass
2. 定义具体产品:Windows风格和Mac风格控件
# 具体产品类:Windows风格按钮
class WindowsButton(Button):def render(self):print("Rendering a Windows button.")# 具体产品类:Windows风格文本框
class WindowsTextBox(TextBox):def render(self):print("Rendering a Windows text box.")# 具体产品类:Mac风格按钮
class MacButton(Button):def render(self):print("Rendering a Mac button.")# 具体产品类:Mac风格文本框
class MacTextBox(TextBox):def render(self):print("Rendering a Mac text box.")
3. 定义抽象工厂:创建按钮和文本框
# 抽象工厂:创建按钮和文本框的工厂
class GUIFactory:def create_button(self):passdef create_textbox(self):pass
4. 定义具体工厂:Windows工厂和Mac工厂
# 具体工厂类:Windows工厂
class WindowsFactory(GUIFactory):def create_button(self):return WindowsButton()def create_textbox(self):return WindowsTextBox()# 具体工厂类:Mac工厂
class MacFactory(GUIFactory):def create_button(self):return MacButton()def create_textbox(self):return MacTextBox()
5. 客户端代码:使用工厂创建控件
# 客户端代码:通过选择工厂来创建不同风格的控件
def client_code(factory: GUIFactory):button = factory.create_button()button.render()  # 渲染按钮textbox = factory.create_textbox()textbox.render()  # 渲染文本框# 使用Windows风格工厂
windows_factory = WindowsFactory()
client_code(windows_factory)# 使用Mac风格工厂
mac_factory = MacFactory()
client_code(mac_factory)
代码解析:
  1. 抽象产品类:Button 和 TextBox 是抽象产品类,定义了控件的共同行为(render 方法)。

  2. 具体产品类:WindowsButtonWindowsTextBoxMacButtonMacTextBox 是具体产品类,它们分别实现了对应的 render 方法,表示不同风格的控件。

  3. 抽象工厂类:GUIFactory 是抽象工厂,定义了创建按钮和文本框的方法。具体工厂类(如 WindowsFactory 和 MacFactory)实现了这些方法,负责创建具体的控件。

  4. 客户端代码:client_code 函数接收一个工厂类对象,然后通过该工厂创建相关的控件。


五、解释给别人:如何讲解抽象工厂模式?

1. 用简单的语言解释

抽象工厂模式允许你通过选择不同的工厂来创建一系列相关的产品,而不需要关心这些产品如何实现。就像在一个工厂中,你可以选择生产Windows风格的控件或Mac风格的控件,工厂会根据你的选择提供完整的产品系列。

2. 为什么要使用抽象工厂模式?

使用抽象工厂模式的最大好处是,它能够确保产品之间的一致性和兼容性。你不需要担心手动组合不同风格的产品,也不需要知道每个具体产品的实现细节。工厂类会根据你的需求创建相关的产品系列,确保它们在同一个系列中的兼容性。


六、总结

通过一系列问题的引导,我们逐步理解了抽象工厂模式的核心概念和实现方式。抽象工厂模式通过将相关的产品创建过程封装到工厂类中,确保了产品族的一致性,并提高了系统的灵活性和可扩展性。然而,它也可能导致类的数量激增,增加系统的复杂性。

通过以上学习过程,我们可以得出以下结论:

  • 抽象工厂模式 通过定义抽象工厂来创建一系列相关的产品对象,并且客户端通过工厂来获取这些产品,而不需要关心具体的产品类。

  • 它通过将对象的创建过程与客户端代码分离,降低了耦合度,并增强了系统的可扩展性。

  • 适用于创建一系列相关产品的场景,如不同风格的UI控件、不同系列的家具等。

抽象工厂模式的优点:
  • 一致性:能够保证同一系列的产品是兼容的。

  • 扩展性:当增加新的产品系列时,只需要增加新的具体工厂类,而不需要修改现有代码。

  • 解耦:客户端不需要知道具体的产品如何实现,只需要关心从工厂获取相关产品。

抽象工厂模式的缺点:
  • 增加类的数量:每增加一个产品系列,需要新增一个具体工厂类和相关的产品类,可能导致类数量的增加。

相关文章:

抽象工厂模式:思考与解读

原文地址:抽象工厂模式:思考与解读 更多内容请关注: 引言 你是否曾经在开发系统时,需要创建一系列相关的对象,而这些对象需要共同协作并保持一致性?假设你有多个不同的产品类型,但它们需要在系统中一起工…...

【综合项目】api系统——基于Node.js、express、mysql等技术

目录 0 前言 1 初始化 2 注册登录 2.1 注册 2.1.1 功能:密码加密(2.3.3) 2.1.1.1 操作 2.1.1.2 bcryptjs详解 2.1.2 插入新用户(2.3.4) 2.1.3 优化:表单数据验证(2.5) …...

Go中slice和map引用传递误区

背景 关于slice和map是指传递还是引用传递,很多文章都分析得模棱两可,其实在Go中只有值传递,但是很多情况下是因为分不清slice和map的底层实现,所以导致很多人在这一块产生疑惑,下面通过代码案例分析slice和map到底是…...

C++ ++++++++++

初始C 注释 变量 常量 关键字 标识符命名规则 数据类型 C规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存 整型 sizeof关键字 浮点型(实型) 有效位数保留七位,带小数点。 这个是保…...

【北京迅为】iTOP-RK3568OpenHarmony系统南向驱动开发-第1章 GPIO基础知识

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工…...

linux在vim中查找和替换

在Linux中使用Vim编辑器查找文本的方法非常直观和强大。Vim是一个高度可配置的文本编辑器,支持多种查找和替换的命令。下面是一些基本的查找命令: 1. 向前查找 要向前查找文本,可以使用以下命令: /text_to_find 例如&#xff0c…...

AWS中使用CloudFront分发API Gateway

首先需要准备一个Lambda function(Lambda->Functions) 还要准备一个证书,要覆盖子域名(AWS Certificate Manager->Certificates)。 1、API Gateway->Create API->REST API->Build->API endpoint type( Edge-optimized )-…...

探秘《矩阵之美》:解锁矩阵的无限魅力

在这个数据驱动的时代,矩阵作为数学中的瑰宝,不仅在理论研究中占据核心地位,更在工程技术、计算机科学、物理学、经济学等众多领域发挥着不可替代的作用。今天,让我们通过中科院大学耿修瑞老师(中科院空天信息研究院研…...

进行性核上性麻痹患者的生活护理指南

进行性核上性麻痹是一种神经系统退行性疾病,合理的生活护理能有效改善症状,提高生活质量。 居家环境要安全。移除地面杂物,铺设防滑垫,安装扶手,降低跌倒风险。在浴室、厨房等湿滑区域要特别加强防护措施。建议在床边、…...

JVM--虚拟机

JVM,即虚拟机,可以简单理解为将字节码文件翻译成机器码的机器。 .class文件-->机器码文件 JVM整体组成部分 1.类加载器 负责从磁盘中加载字节码文件到JVM中 2.运行时数据区 按照不同的数据分区进行存储(方法区,堆,栈,本地方…...

pyside6学习专栏(八):在PySide6中使用matplotlib库绘制三维图形

本代码原来是PySide6官网的一个示例程序,我对其进行的详细的注释,同时增加了一个功能:加载显示cass的地形图坐标数据示例,示例可显示以下几种三维图形 程序运行界面如下: 代码如下: # -*- coding: utf-8 -…...

松灵机器人地盘 安装 ros 驱动 并且 发布ros 指令进行控制

安装驱动 $ cd ~/catkin_ws/src $ git clone https://github.com/agilexrobotics/ugv_sdk.git $ git clone https://github.com/agilexrobotics/scout_ros.git $ cd .. $ catkin_make安装 ● 使能 gs_usb 内核模块 ● 设置 500k 波特率和使能 can-to-usb 适配器 sudo modp…...

Highcharts 配置语法详解

Highcharts 配置语法详解 引言 Highcharts 是一个功能强大的图表库,广泛应用于数据可视化领域。本文将详细介绍 Highcharts 的配置语法,帮助您快速上手并制作出精美、实用的图表。 高级配置结构 Highcharts 的配置对象通常包含以下几部分&#xff1a…...

python力扣2:两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这两个数都不会以 0 开…...

服务器间迁移conda环境

注意:可使用迁移miniconda文件 or 迁移yaml文件两种方式,推荐前者,基本无bug! 一、迁移miniconda文件: 拷贝旧机器的miniconda文件文件到新机器: 内网拷贝:scp -r mazhf192.168.1.233:~/miniconda3 ~/ 外…...

LeetCode第58题_最后一个单词的长度

LeetCode 第58题:最后一个单词的长度 题目描述 给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中最后一个单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 难度 简单 题目链接 点…...

Python 绘制迷宫游戏,自带最优解路线

1、需要安装pygame 2、上下左右移动,空格实现物体所在位置到终点的路线,会有虚线绘制。 import pygame import random import math# 迷宫单元格类 class Cell:def __init__(self, x, y):self.x xself.y yself.walls {top: True, right: True, botto…...

恶意 SSP 注入收集密码

SSP 安全服务提供者,是微软提供的与安全有关的函数接口,用户可根据自己的需求调用 SSP 接口实现高度自定义的身份验证等安全功能。攻击者注入恶意的 SSP 接口覆盖微软默认的某些安全功能,导致用户一旦进行身份验证,恶意的 SSP 将保…...

Llama 2中的Margin Loss:为何更高的Margin导致更大的Loss和梯度?

Llama 2中的Margin Loss:为何更高的Margin导致更大的Loss和梯度? 在《Llama 2: Open Foundation and Fine-Tuned Chat Models》论文中,作者在强化学习与人类反馈(RLHF)的Reward Model训练中引入了Margin Loss的概念&a…...

Python----数据分析(Numpy:安装,数组创建,切片和索引,数组的属性,数据类型,数组形状,数组的运算,基本函数)

一、 Numpy库简介 1.1、概念 NumPy(Numerical Python)是一个开源的Python科学计算库,旨在为Python提供 高性能的多维数组对象和一系列工具。NumPy数组是Python数据分析的基础,许多 其他的数据处理库(如Pandas、SciPy)都依赖于Num…...

Android Logcat 高效调试指南

工具概览 Logcat 是 Android SDK 提供的命令行日志工具&#xff0c;支持灵活过滤、格式定制和实时监控&#xff0c;官方文档详见 Android Developer。 基础用法 命令格式 [adb] logcat [<option>] ... [<filter-spec>] ... 执行方式 直接调用&#xff08;通过ADB守…...

Pytest之fixture的常见用法

文章目录 1.前言2.使用fixture执行前置操作3.使用conftest共享fixture4.使用yield执行后置操作 1.前言 在pytest中&#xff0c;fixture是一个非常强大和灵活的功能&#xff0c;用于为测试函数提供固定的测试数据、测试环境或执行一些前置和后置操作等&#xff0c; 与setup和te…...

如何把网络ip改为动态:全面指南

在数字化时代&#xff0c;网络IP地址作为设备在网络中的唯一标识&#xff0c;扮演着至关重要的角色。随着网络环境的不断变化&#xff0c;静态IP地址的局限性逐渐显现&#xff0c;而动态IP地址则因其灵活性和安全性受到越来越多用户的青睐。那么&#xff0c;如何把网络IP改为动…...

anythingLLM和deepseek4j和milvus组合建立RAG知识库

1、deepseek本地化部署使用 ollama 下载模型 Tags bge-m3 bge-m3:latest deepseek-r1:32b deepseek-r1:8b 2、安装好向量数据库 milvus docker安装milvus单机版-CSDN博客 3、安装 anythingLLM AnythingLLM | The all-in-one AI application for everyone …...

和鲸科技推出人工智能通识课程解决方案,助力AI人才培养

2025年2月&#xff0c;教育部副部长吴岩应港澳特区政府邀请&#xff0c;率团赴港澳宣讲《教育强国建设规划纲要 (2024—2035 年)》。在港澳期间&#xff0c;吴岩阐释了教育强国目标的任务&#xff0c;并与特区政府官员交流推进人工智能人才培养的办法。这一系列行动体现出人工智…...

当我删除word文件时无法删除,提示:操作无法完成,因为已在Microsoft Word中打开

现象&#xff1a; 查看电脑桌面下方的任务栏&#xff0c;明明已经关闭了WPS和WORD软件&#xff0c;但是打开word文档时还是提示&#xff1a; 解决方法步骤&#xff1a; 1、按一下键盘上的ctrl Shift Esc 键打开任务管理器 2、在进程中找到如下&#xff1a; 快速找到的方法…...

高频面试题(含笔试高频算法整理)基本总结回顾3

目录 一、基本面试流程回顾 二、基本高频算法题展示 三、基本面试题总结回顾 &#xff08;一&#xff09;Java高频面试题整理 &#xff08;二&#xff09;JVM相关面试问题整理 &#xff08;三&#xff09;MySQL相关面试问题整理 &#xff08;四&#xff09;Redis相关面试…...

Python中字符串的常用操作

一、r原样输出 在 Python 中&#xff0c;字符串前加 r&#xff08;即 r"string" 或 rstring&#xff09;表示创建一个原始字符串&#xff08;raw string&#xff09;。下面详细介绍原始字符串的特点、使用场景及与普通字符串的对比。 特点 忽略转义字符&#xff1…...

卷积神经网络(cnn,类似lenet-1,八)

我们第一层用卷积核&#xff0c;前面已经成功&#xff0c;现在我们用两层卷积核&#xff1a; 结构如下&#xff0c;是不是很想lenet-1&#xff0c;其实我们24年就实现了sigmoid版本的&#xff1a; cnn突破九&#xff08;我们的五层卷积核bpnet网络就是lenet-1&#xff09;-CS…...

Win32 C++ 电源计划操作

CPowerCfgUtils.h #pragma once#include <Windows.h> #include <powrprof.h>// https://learn.microsoft.com/zh-cn/windows/win32/api/powrprof/?sourcerecommendations//节能 //DEFINE_GUID(GUID_MAX_POWER_SAVINGS, 0xA1841308, 0x3541, 0x4FAB, 0xBC, 0x81, …...