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

【python高级】设计模式、类工厂、对象工厂

一、说明

        最近试着读Design pattern, 不过有些概念实在太抽象了, 整理一下自己所学抽象工厂的精神,就是要有abstract class(not implement),而所有不同种类的对象,都是继承这个abstract class,但是使用者只知道interface的接口就好。

二、关于抽象类的使用案例

2.1 抽象类

        很抽象吧,直接举例会比较实在,今天我开发了一个Qt windows app,Qt是跨平台的框架,所以Qt假设里面有个button class

class Button:def clicked():print(clicked)

        这个Button绝对不会这么简单,他还要跟不同操作系统兼容,所以就会有mac的button,windows的button,我们就可以先开个抽象类

class Button(ABC):@abstractmethoddef clicked(self):passclass   WinButton(Button):def clicked(self):print('click winbutton')class MacButton(Button):def clicked(self): print('click macbutton')

        qt的interface可是非常多对象的,有button还有checkbox等等,这样我写程序的时候就要打self.btn = WinButton()这样子???,然后今天要打包到Mac上,又要改成self.btn = MacButton(),这样子是非常没有效率的...,能不能把这个作业系统的环境提取出来呢???

2.2 关于工厂

        白话就是,我们需要一个工厂,这个工厂可以帮我们呼叫下面不同的控件,例如WinFactory就是要给我windows的控件

class GUIFactory(ABC):@abstractmethoddef create_button(self):pass@abstractmethoddef create_checkbox(self):passclass WinFactory(GUIFactory):def create_button(self):return WinButton()def create_checkbox(self):return WinCheckBox() class MacFactory(GUIFactory):def create_button(self):return MacButton()def create_checkbox(self):return MacCheckBox()

        换个譬喻,你今天要吃大餐,而有前菜,主餐,甜点,而大餐有不同风格,你不会想要这样说: 主厨我要日式前菜,日式主餐,日式甜点。而是会想要这样说: 日式主厨,我要前菜、主餐、甜点。这边的日式主厨就是工厂啦!!主厨要会煮菜 上菜 切菜 等 这个就是抽象工厂,而日式主厨,西式主厨,就是工厂。

        那这样来看看前面的关系图怎么画

资料源: 抽象工厂设计模式

2.3 完整代码: 

from abc import ABC, abstractmethod
class GUIFactory(ABC):@abstractmethoddef create_button(self):pass@abstractmethoddef create_checkbox(self):pass
class WinFactory(GUIFactory):def create_button(self):return WinButton()def create_checkbox(self):return WinCheckBox()
class MacFactory(GUIFactory):def create_button(self):return MacButton()def create_checkbox(self):return MacCheckBox()
class Button(ABC):@abstractmethoddef clicked(self):passclass WinButton(Button):def clicked(self):print('click winbutton')class MacButton(Button):def clicked(self):print('click macbutton')
class CheckBox(ABC):@abstractmethoddef checked(self):passclass WinCheckBox(CheckBox):def checked(self):print('check wincheckbox')
class MacCheckBox(CheckBox):def checked(self):print('check maccheckbox')
class Application:def __init__(self, factory):self.button = factory.create_button()self.checkbox = factory.create_checkbox()if __name__ == "__main__":app = Application(MacFactory())app.button.clicked()

     注意,这样子,对用户而言,就是Application最后call的时候传入引数(Mac or Win Factory),这边甚至能加个if else直接判断当前os。最后那个对用户而言 看到的都是app
app.button, app.checkbox, 早就已经透过工厂创造好啦

2.4 总结

        抽象工厂模式: 对用户来说单一接口,所有class需要继承abstract class。抽象工厂为你提供了一个接口, 可用于创建每个系列产品的对象。 只要代码通过该接口创建对象, 那么你就不会生成与应用程序已生成的产品类型不一致的产品。

设计模式

抽象工厂模式

三、什么是类工厂

3.1 类工厂定义

  • 类工厂本质

        类工厂就是一个在运行时创建类的函数。 即允许创建类时根据情况决定其属性,比如,根据用户输入创建属性。

  • 类工厂函数

        是一个用于创建并返回类的函数。

3.2 理解类工厂函数-函数返回一个“类”的变量

使用type创建类如下

def init(self, name):self.name = name
def eat(self):pass
def go_to_vet(self):print "go_to_vet"
return type('Animal', (object,), {'__doc__': 'A class representing an arbitrary animal.','__init__': init,'eat': eat,'go_to_vet': go_to_vet,
})

这种方式的缺点:

  • 这种写法会将类Animal的函数置于和Animal同一层命名空间下,不利于层次化。因此一般不使用type之间创建。
  • 如果真需要使用type,则可以将其封装放入一个函数中。如下:

3.3 将类的“内脏”封装到函数中

下列示例表示

def create_animal_class():def init(self, name):self.name = namedef eat(self):passdef go_to_vet(self):print(self.name)return type('Animal', (object,), {'__doc__': 'A class representing an arbitrary animal.','__init__': init,'eat': eat,'go_to_vet': go_to_vet,})Animal1 = create_animal_class( )
dog = Animal1("my dog")
dog.go_to_vet()
cat = Animal1("my cat")
cat.go_to_vet()

3.4  封装到函数内的class关键词

        通过函数调用即可获得一个自定义创建的Animal类。使用class关键字创建效果相同:

    def create_animal_class():class Animal(object):def init(self, name):self.name = namedef eat(self):passdef go_to_vet(self):print "go_to_vet"return AnimalAnimal = create_animal_class()print Animal   #<class '__main__.Animal'>

3.5 编写类工厂的时机

  • 在需要基于运行时的信息(如用户输入)创建类时需要编写类工厂
    • 如果在编码时并不知道需要赋值给类的属性时
    • 类工厂示例:(创建类工厂的原因:假如说是为大量不同的第三方网站提供凭据的服务,则需要有多重不同的验证方式。该工厂可以根据数据库查询结果生成属性) 
#-*- coding:utf-8 -*-
def get_credential_class(use_proxy=False, tfa=False):if use_proxy:keys = ['service_name', 'email_address']  # 通过代理身份验证所要的密匙else:keys = ['username', 'password']if tfa:keys.append('tfa_token')class Credential(object):expected_keys = set(keys)def __init__(self, **kwargs):if self.expected_keys != set(kwargs.keys()):raise ValueError('Keys do not match')for k, v in kwargs.items():setattr(self, k, v)return Credentialcred = get_credential_class(0,0)
print(cred)

运行结果:
<class ‘main.Credential’>

  • 避免类属性一致性问题:处理类与实例之间属性不同的问题
class C(object):foo = 'bar'class I(object):def __init__(self):self.foo = 'bar'
print C.foo()
print I.foo()   # AttributeErrorc1 = C()   
c2 = C()  c1.foo = 'baz'
print c1.foo   #baz
print c2.foo   # barC.foo = 'bacon'
print c1.foo   #baz
print c2.foo   #baconprint c1.__dict__    # {'foo': 'baz'}
print c2.__dict__    #{}

 print I.foo() # AttributeError原因:
foo作为C的一个实例被实例化,但并不作为I的属性被实例化。
由于直接访问I而不是I的实例,因此__init__函数还没有被允许。
一个对象的属性查找顺序遵循首先查找实例对象自己,然后是类,接着是类的父类。
本质:__dict__属性存储着对象的所有属性(和值)
注意:一些内置的数据类型是没有__dict__属性的:
int,list,dict等这些常用的数据类型是没有__dict__属性的,其实这是可预料的,就算给了它们dict属性也没啥用,毕竟它们只是用来做数据容器的。

属性:指一个对象的数据或者函数
    - 属性的访问:通过句话(.)访问属性
    - 支持运行中添加和修改属性
字段:类的数据变量,例如:name='scolia'
方法:类里面的函数。可分为:
    - 实例方法:第一个参数需要是self,它表示一个具体的实例本身。
    - 类方法:用classmethod,它的第一个参数不是self,是cls,它表示这个类本身。类方法是那些并不需要类的实例就可以执行的方法
    - 静态方法:用staticmethod,可以无视self,而将这个方法当成一个普通的函数使用
 

#-*- coding:utf-8 -*-
class cls:clsvar = 1   #普通字段def __init__(self):self.insvar = 2ins1 = cls()
ins2 = cls()ins1.clsvar = 20
print cls.clsvar     #输出结果为1
print ins1.clsvar    #输出结果为20
print ins2.clsvar    #输出结果为1#用类名为类变量重新赋值并打印
cls.clsvar = 10
print cls.clsvar     #输出结果为10
print ins1.clsvar    #输出结果为20
print ins2.clsvar    #输出结果为10#这次直接给实例1没有在类中定义的变量赋值
ins1.x = 11
print ins1.x         #输出结果为11#然后再用类名给类中没有定义的变量赋值
cls.m = 21
print cls.m          #输出结果为21#再创建一个实例ins3,然后打印一下ins3的变量
ins3 = cls()
print ins3.insvar    #输出结果为2
print ins3.clsvar    #输出结果为10
print ins3.m         #输出结果为21
print ins3.x         #报错AttributeErro

四、类方法限制 

class C(object):foo = 'bar'@classmethoddef classfoo(cls):return cls.fooprint c1.classfoo()  #bacon
print c2.classfoo()  #bacon

注意:类方法无法访问实例属性,它们并不需要一个实例,但需要类本身。因此c1.classfoo使用的是类的foo而不是实例c1的foo

4.1 使用类工厂

        使用时机:当你继承一个现有类并且所依赖的类属性必须调整时。类工厂是生成带有重载属性的恰当子类的一种恰当方式。

class C(object):foo = 'bar'@classmethoddef classfoo(cls):return cls.foodef create_C_subclass(new_foo):class SubC(C):foo = new_fooreturn SubCS = create_C_subclass('spam')
print S.classfoo()  #spam
E = create_C_subclass('eggs')
print E.classfoo()  #eggs

执行C子类的classfoo类方法创建类的方式返回需要的结果。

4.2 单例模式

        让类工厂函数难以使用的一点是类工厂返回的是类而不是类的实例。如果一个实例,则必须调用类工厂函数返回的结果才可以。单例模式是一种只允许一个实例的类模式。
        类工厂示例:

class C(object):foo = 'bar'@classmethoddef classfoo(cls):return cls.foodef CPrime(new_foo='bar'):if new_foo == 'bar':return C()class SubC(C):foo = new_fooreturn SubCEE = CPrime('bar')
FF = CPrime('bar1')
print EE  #<__main__.C object at 0x01777CB0>
print FF  #<class '__main__.SubC'>

五、实例的工厂模式

        工厂模式是一个在软件开发中用来创建对象的设计模式。

        工厂模式包涵一个超类。这个超类提供一个抽象化的接口来创建一个特定类型的对象,而不是决定哪个对象可以被创建。

        为了实现此方法,需要创建一个工厂类并返回所需对象。

        当程序运行输入一个“类型”的时候,需要创建于此相应的对象。这就用到了工厂模式。在如此情形中,实现代码基于工厂模式,可以达到可扩展,可维护的代码。当增加一个新的类型,不在需要修改已存在的类,只增加能够产生新类型的子类。

        简短的说,当以下情形可以使用工厂模式:

  • 1.不知道用户想要创建什么样的对象
  • 2.当你想要创建一个可扩展的关联在创建类与支持创建对象的类之间。
"""
工厂模式:
根据需求产生对象。
"""
from typing import Anyclass Clothes:"""服装工厂类"""def __init__(self,name):self.name = namedef create(self):passclass Lovely(Clothes):def __init__(self, name):super().__init__(name)def create(self):print(f"{self.name} 生产 汉服")class Cool(Clothes):def __init__(self, name):super().__init__(name)def create(self):print(f"{self.name} 生产 酷酷的、帅")class Lipstick(Clothes):def __init__(self, name):super().__init__(name)def create(self):print(f"{self.name} 生产 死亡芭比粉")class Shoes(Clothes):def __init__(self, name):super().__init__(name)def create(self):print(f"{self.name}生产 红色高跟鞋")class Shoes2(Clothes):def __init__(self, name):super().__init__(name)def create(self):print(f"{self.name}生产 蓝色高跟鞋")class Requirement:"""定义一个需求类"""@staticmethoddef creatNeed(need):if need == "死亡芭比粉":return Lipstick("死亡芭比粉")elif need == "酷酷的、帅":return Cool("酷酷的、帅")elif need == "汉服":return Lovely("汉服")elif need == "红色高跟鞋":return Shoes("红色高跟鞋")elif need == "蓝色高跟鞋":return Shoes2("蓝色高跟鞋")# Requirement.creatNeed("死亡芭比粉").create()
# Requirement.creatNeed("红色高跟鞋").create()
# Requirement.creatNeed("汉服").create()with open("create.txt","r",encoding="utf-8")as f_r:content = f_r.read()# print(content)
Requirement.creatNeed(content).create()# class StudentNum:
#     num = 0
#
#     @classmethod
#     def add_num(cls):
#         cls.num += 1
#
#     @classmethod
#     def get_num(cls):
#         return cls.num
#
#     def __new__(cls) -> Any:
#         StudentNum.add_num()
#         return super().__new__(cls)
#
#
# class Student(StudentNum):
#     def __init__(self):
#         self.name = ""
# a = Student()
# b = Student()
# c = Student()
# print(StudentNum.get_num())

相关文章:

【python高级】设计模式、类工厂、对象工厂

一、说明 最近试着读Design pattern&#xff0c; 不过有些概念实在太抽象了&#xff0c; 整理一下自己所学抽象工厂的精神&#xff0c;就是要有abstract class&#xff08;not implement&#xff09;&#xff0c;而所有不同种类的对象&#xff0c;都是继承这个abstract class&a…...

Flink的算子列表状态的使用

背景 算子的列表状态是平时比较常见的一种状态&#xff0c;本文通过官方的例子来看一下怎么使用算子列表状态 算子列表状态 算子列表状态支持应用的并行度扩缩容&#xff0c;如下所示: 使用方法参见官方示例&#xff0c;我加了几个注解&#xff1a; public class Bufferin…...

使用 Github Actions 工作流自动部署 Github Pages

GitHub-Actions actions顾名思义就是一堆动作&#xff0c;是一个持续集成服务&#xff0c;持续集成包含了拉代码、运行测试、编译代码、登录远程服务器&#xff0c;发布到第三方服务等等的操作&#xff0c;GitHub将这些操作称为actions。 概念&#xff1a;Workflows, Events,…...

Xposed hook 抖音账户信息

本篇主要讲下hook获取 抖音账户的相关信息&#xff0c;直接上代码。 public class DouHook {private static final String TAG "DouHook";public static void hook(XC_LoadPackage.LoadPackageParam lpparam) {Log.e(TAG, "DouHook start");if (lpparam …...

回顾 | E³CI效能认知与改进论坛,助力企业研发效能度量和提升

2023年8月&#xff0c;TiD质量竞争力大会组委会和ECI专家委员会成功举办TiD大时段课程“度量驱动研发效能提升”与“ECI效能认知与改进论坛”。与会专家以《ECI软件研发效能度量规范》团体标准为要点&#xff0c;为企业研发效能度量和提升分享诸多实践成果与经验。 《ECI软件研…...

科技的成就(五十二)

405、微信公众平台正式上线 "1995 年 8 月 24 日&#xff0c;微软发布 Windows 95。Windows 95 极大地改进了前续系统的图形用户界面&#xff0c;首次推出了开始菜单、任务栏、最大化、最小化窗口以及关闭按钮。此外&#xff0c;Windows 95 最大程度兼容当时的 MS-DOS 和 …...

【23种设计模式】装饰器模式

个人主页&#xff1a;金鳞踏雨 个人简介&#xff1a;大家好&#xff0c;我是金鳞&#xff0c;一个初出茅庐的Java小白 目前状况&#xff1a;22届普通本科毕业生&#xff0c;几经波折了&#xff0c;现在任职于一家国内大型知名日化公司&#xff0c;从事Java开发工作 我的博客&am…...

解决IDEA中SpringBoot项目创建多个子模块时配置文件小绿叶图标异常问题

在新建子模块下创建配置文件&#xff1a; 在子模块gateway中新建的配置文件,正常情况下配置文件左侧是小树叶标识&#xff0c;而这次新建application-dev.yml是个小树叶标识&#xff0c;bootstrap.yml是个方框。 看其他方案都是在project structure中设置&#xff0c;但未显示…...

【马蹄集】—— 概率论专题

概率论专题 目录 MT2226 抽奖概率MT2227 饿饿&#xff01;饭饭&#xff01;MT2228 甜甜花的研究MT2229 赌石MT2230 square MT2226 抽奖概率 难度&#xff1a;黄金    时间限制&#xff1a;1秒    占用内存&#xff1a;128M 题目描述 小码哥正在进行抽奖&#xff0c;箱子里有…...

Spring 6整合单元测试JUnit4和JUnit5

单元测试&#xff1a;JUnit 在之前的测试方法中&#xff0c;几乎都能看到以下的两行代码&#xff1a; ApplicationContext context new ClassPathXmlApplicationContext("xxx.xml"); Xxxx xxx context.getBean(Xxxx.class);这两行代码的作用是创建Spring容器&…...

【好书推荐】深入理解现代JavaScript

作者介绍 T. J. Crowder是一位拥有30年经验的软件工程师。在他的整个职业生涯中&#xff0c;他至少有一半时间是在使用JavaScript从事开发工作。他经营着软件承包和产品公司Farsight Software。他经常在Stack Overflow上为人们提供帮助&#xff0c;他是十大贡献者之一和JavaScr…...

高效协同: 打造分布式系统的三种模式

在构建分布式系统时&#xff0c;分布式协调是否总是必要选项&#xff1f;本文通过一些实际的例子讨论了这一问题&#xff0c;并通过把问题区分为是否具有单调性做为是否需要分布式协调的标准。原文: Avoiding Coordination Cost: Three Patterns for Building Efficient Distri…...

机器学习-无监督学习之聚类

文章目录 K均值聚类密度聚类&#xff08;DBSCAN&#xff09;层次聚类AGNES 算法DIANA算法 高斯混合模型聚类聚类效果的衡量指标小结 K均值聚类 步骤&#xff1a; Step1&#xff1a;随机选取样本作为初始均值向量。 Step2&#xff1a;计算样本点到各均值向量的距离&#xff0c;…...

智能垃圾桶丨悦享便捷生活

垃圾桶是人们日常生活所必不可少的必需品&#xff0c;它让生活中所产生的垃圾有了一个正确的存放地方。随着生产技术的迅速发展&#xff0c;垃圾桶也得以更新换代。由最初的简单式的圆筒式垃圾桶&#xff0c;到现在出现的感应式垃圾桶、智能语音控制垃圾桶&#xff0c;垃圾桶也…...

【数据结构】线性表(一)线性表的定义及其基本操作(顺序表插入、删除、查找、修改)

目录 一、线性表 1. 线性表的定义 2. 线性表的要素 二、线性表的基本操作 三、线性表的顺序存储结构 1. 定义 2. 顺序表的操作 a. 插入操作 b. 删除操作 c. 查找操作 d. 修改操作 e. 代码实例 一、线性表 1. 线性表的定义 一个线性表是由零个或多个具有相同…...

MyBatis的自定义插件

MyBatis的自定义插件 前置知识 MyBatis 可以拦截的四大组件 Executor - 执行器StatementHandler - SQL 语句构造器ParameterHandler - 参数处理器ResultSetHandler - 结果集处理器 自定义 MyBatis 插件 /*** 打印 sql 执行的时间插件*/ Intercepts(// 指定拦截器拦截的对象…...

生物制剂\化工\化妆品等质检损耗、制造误差处理作业流程图(ODOO15/16)

生物制剂、化工、化妆品等行业&#xff0c;因为产品为液体&#xff0c;产品形态和质量容易在各个业务环节发生变化&#xff0c;常常导致实物和账面数据不一致&#xff0c;如果企业业务流程不清晰&#xff0c;会导致系统大量的库存差异&#xff0c;以及财务难以核算的问题&#…...

vbv介绍

VBV模型 VBV即Video Buffer Verifier(视频缓冲区校验器)。 本质是encoder端的一个虚拟buffer,可以将VBV当做一个容量受限的管道,有一个上限容量值和下限容量值,在经过此管道的调节之后能限制编码码率在上限容量值和下限容量值之间。VBV对标NetEq中的那几个buffer(decoder b…...

Linux CentOS 8(网卡的配置与管理)

Linux CentOS 8&#xff08;网卡的配置与管理&#xff09; 目录 一、项目介绍二、命令行三、配置文件四、图形画界面的网卡IP配置4.1 方法一4.2 方法二 一、项目介绍 Linux服务器的网络配置是Linux系统管理的底层建筑&#xff0c;没有网络配置&#xff0c;服务器之间就不能相互…...

python -m pip install 和 pip install 的区别解析

python -m pip install 和 pip install 的区别解析 python -m pip install 使用了 -m 参数来确保以 Python 模块的形式运行 pip&#xff0c;适用于确保在不同的环境中正确使用 pip&#xff0c;这篇文章主要介绍了python -m pip install 和 pip install 的区别,需要的朋友可以参…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...