《系统架构设计》-03-软件结构体系和架构风格

news2024/11/15 19:28:32

文章目录

  • 1. 软件结构体系
    • 1.1 抽象(Abstract)
      • 1.1.1 抽象的应用
      • 1.1.2 不同层次的抽象
    • 1.2 组件(Component)
      • 1.2.1 定义
      • 1.2.2 切入点
    • 1.3 组织过程资产(Organizational Process Assets)
      • 1.3.1 定义
      • 1.3.2 作用
    • 1.4 体系结构
      • 1.4.1 定义和表现形式
      • 1.4.2 作用
  • 2. 架构风格
    • 2.1 分布式
      • 2.1.1 消息传递
        • 消息传递系统模型
        • 业务服务整合
      • 2.1.2 发布-订阅
        • 结构图
        • 场景示例
      • 2.1.3 Broker
      • 2.1.4 三种架构对比
    • 2.2 事件驱动架构(Event Driven Architecture,EDA)
      • 2.2.1 事件处理系统的抽象和设计
        • 设计初衷
      • 2.2.2 IO操作与事件驱动
        • 1)概述
        • 2)主流的IO操作模式
      • 2.2.3 Reactor模式
        • 1)基本模式
        • 2)组件化的表现形式
        • 3)异步Handler
    • 2.3 系统结构
      • 2.3.1 切入点
      • 2.3.2 分层结构
      • 2.3.3 交互型结构
        • 概述
        • MVC风格
        • MVP风格
    • 2.4 消息总线
      • 2.4.1 作用
      • 2.4.2 传递过程
        • 2.4.3 优缺点
    • 2.5 适配与扩展(管道-过滤器风格)
      • 2.5.1 概述
      • 2.5.2 示例
      • 2.5.3 管道-过滤器 VS 派发风格(Dispatching)

1. 软件结构体系

  • 什么是软件结构体系
    软件体系结构包括一组软件组件、软件组件的外部可见特性及其相互关系,强调软件设计必须从系统中抽象出某些信息,所以软件体系结构设计本质是一种抽象工作。

  • 软件结构体系的作用
    随着软件复杂度的提升及软件开发技术的进步,更多的业务系统已不再或不需要关注于算法设计和数据结构,系统的层次化设计理念及高层次的结构化设计成为系统开发成败的决定性因素,即软件体系结构应运而生。

1.1 抽象(Abstract)

1.1.1 抽象的应用

作为系统分析和架构设计的基本手段之一,在面向对象领域、设计模式领域及本节的软件体系结构领域都有广泛应用。

1.1.2 不同层次的抽象

如图,是抽象的层次的发展过程,体现了不同时期使用的抽象方法。
在这里插入图片描述
体系结构级别抽象的结果就是软件体系结构,它是系统总体结构的表现形式,是整个软件抽象的最高层次。

1.2 组件(Component)

1.2.1 定义

是软件体系结构的基本元素

1.2.2 切入点

举例:

  • 功能特性:描述组件所实现的整体功能
  • 非功能特性:描述组件的执行效率、处理能力、环境假设和整体特性
  • 结构特性:描述组件如何与其他部件集成在一起,以构成系统信息
  • 家族特性:描述了相同或相关组件之间的关系

在软件开发生命周期中,软件体系结构设计作为一种高层设计位于需求分析和底层设计之间,如图2-2所示。通过开发特定应用领域的体系结构并形成组织级别的体系结构库是一项有价值的组织过程资产建设工作。
在这里插入图片描述

CSDN水印打的比较坑,遮盖部分是“可复用设计库”

1.3 组织过程资产(Organizational Process Assets)

1.3.1 定义

是指一个组织中用于影响项目成功的所有资产总和。

如:规章制度、指导方针、规范标准、操作程序、工作流程、行为准则和工具方法等

1.3.2 作用

通过建立体系机构的作用:

  • 促进广大开发人员形成习惯性模式
  • 促进对设计的重用
  • 提供软件可视化视图
  • 便于相关关系人理解系统

1.4 体系结构

1.4.1 定义和表现形式

是一个高度抽象的层次,本文归为3种主要的表现形式

  • 风格(Style):描述某一特定应用领域中系统组织和表现的惯用方式
  • 模式(Pattern):
  • 模型(Model):

1.4.2 作用

  • 可以明确如何对软件设计成分进行整理和安排,并且对这些整理和安排加以限制,从而形成一种设计软件的特定套路
  • 能够反映领域中众多系统所共有的结构和语义特性,并为我们提供描述系统的术语表和一组指导构建系统的规则

后文将对这三种表现形式进行讲解。

2. 架构风格

描述某一特定应用领域中系统组织和表现的惯用方式

2.1 分布式

现代软件开发的一大现状和问题就是容易形成信息孤岛,分布式作为一种基础架构风格为不同系统之间的交互提供通信范式,从而有效屏蔽底层平台细节。分布式架构风格有以下3种主要的表现形式:

2.1.1 消息传递

通过消息传递的相互作用可以实现分布式。

消息传递系统模型

  • 客户端:消息的发送者、生产者
  • 服务端:消息的接受者、消费者
  • 通道:在消息传递系统中连接消息发送者和接收者的媒介
  • 端点:提取专门与消息通道发生直接交互的组件,以解耦客户端和服务端
    消息传递系统

业务服务整合

通过消息传递可以进行业务服务整合。

下图是基于消息传递的服务整合思路:
在这里插入图片描述

其中包含一个独立的业务服务。该业务服务的输入来自于输入通道,而输出则通过输出通道传递到别的消费者。
通常,在由生产者作为起点、消费者作为终点的业务链路中可能存储一个或多个业务服务。这些业务服务都通过消息通道进行数据传输。显然消息通道具备良好的扩展性,一个消息通道的输出可以作为另一个消息通道的输入,多个消息通道即构成一个消息通道链。我们可以把业务服务嵌入到消息通道链的相应节点中,从而构成完整的业务链路。

2.1.2 发布-订阅

发布-订阅风格,通过异步交换事件来提供分布式架构所需实现的交互功能

结构图

下图为该种风格的结构图。
在这里插入图片描述

  • 事件是整个结构能够运行所依赖的基本数据模型
  • 发布者发布事件
  • 订阅者关注自身所想关注的事件
  • 发布者和订阅者并不需要感知对方的存在,两者之间通过传输事件的基础设施进行完全解耦。

场景示例

场景需求:

  • 存在两个独立的系统,分别为系统A和系统B。
  • 系统A负责管理用户
  • 系统B需要在当系统A中用户被创建和更新时能够获取通知并进行响应。

这是一个分布式的业务场景。我们可以通过远程方法调用等方式进行系统A和系统B之间跨进程的交互,但更好的一种方式是通过触发创建和更新事件并进行解耦。

使用发布-订阅风格

  • 先声明事件,系统内部或外部的组件都可以对这些事件中进行订阅。
  • 当触发一个事件时,系统会自动调用在这个事件中注册的所有过程。

在这里插入图片描述
该图中:

  • 声明了用户创建事件(UserCreatedEvent)和用户更新事件(UserUpdatedEvent),
  • UserCreatedHandler和UserUpdatedHandler分别是针对这两个事件的处理程序
  • 通过事件分离器(EventDispatcher)把所有Event和Handler进行关联,相当于传输事件的基础设施
  • Event和Handler提供了高层次的抽象,具体的Event和Handler实现者可以分布在不同的业务系统中从而构成分布式运行环境

2.1.3 Broker

常见的一种架构风格,分布式系统之间通过远程过程调用(Remote Procedure Call,RPC)进行相互作用。
服务端应用组件注册自己到Broker,通过暴露接口的方式允许客户端接入服务。客户端则通过Broker发送请求,Broker转发请求到服务端,调用服务端应用组件并将生成的结果回发给客户端。通过Broker,业务服务之间可以通过发送请求访问远程的服务:

在这里插入图片描述

Broker中存在几个核心组件:

  • 客户端:
  • 服务器端(Server)
  • 代理(Proxy)
  • 客户端Broker:通过客户端Broker,客户端可以发现远程服务

客户端Broker保证了通讯的透明性,使Client调用远程服务就像调用本地的服务一样。

  • 服务端Broker:提供注册服务的接口给Server

调用过程:

  • 服务器端Broker需要提供注册服务的接口给Server
  • 客户端可以通过客户端Broker发现远程服务,客户端Broker保证了通讯的透明性,使Client调用远程服务就像调用本地的服务一样。
  • 通过客户端Broker和服务器端Broker之间的数据发送和接收实现分布式环境下的远程通信。

2.1.4 三种架构对比

消息传递机制同时面向一对一和一对多,加之技术和时间上的解耦,使得以各种消息中间件为代表的消息传递系统在分布式系统的构建过程中得到广泛应用。

在这里插入图片描述

2.2 事件驱动架构(Event Driven Architecture,EDA)

2.2.1 事件处理系统的抽象和设计

设计初衷

由于异步性和并发性,导致:

  • 事件到达的时机是系统无法提前确定的
  • 一个系统中往往需要同时处理多种事件类型。

因此,对事件的处理,我们同样需要设计一种抽象的框架和流程。

把事件驱动系统按照事件的来源和处理过程分成3个层次:

  • 事件源:
    套接口(Socket)即是事件产生的源头
  • 事件分离器
    操作系统级别的select/poll/epoll程序对应事件分离器
  • 事件响应程序
    业务系统中各种应用程序

通过这种抽象,我们认识到在网络通信模型中,事件源和事件分离器往往并不属于应用程序所能控制的范围之内,应用程序能做的只是对事件的响应。

一个事件在其生命周期中一般会经历发起、接收、分离、分发、处理等阶段。当事件到达事件处理系统,是采用多线程等待事件发生的方式处理事件,亦或采用单线程无限制阻塞单一事件源的方式处理事件,还是两者兼而有之,我们同样面临设计上的需求和选择。一般认为,事件处理系统需要能够处理多个事件源;同时,能够封装事件分离和分发操作,也就是说事件的分离和分发操作应该对应用系统透明;最后,应用程序对事件的处理过程可以串行化以简化开发。在具体介绍事件处理系统的实现模式之前,我们先来看一下IO(Input / Output,输入/输出)操作和事件驱动之间的关系。

2.2.2 IO操作与事件驱动

1)概述

  • 内核空间和用户空间

    • 内核空间(Kernel Space):内核空间主要存放内核代码和数据,是供系统进程使用的空间。
    • 用户空间(User Space):用户空间主要存放的是用户代码和数据,是供用户进程使用的空间。
  • IO操作都两个阶段:

    • 将网络收到的数据拷贝到内核空间的临时缓冲区中
    • 将内核空间临时缓冲区中的数据拷贝到用户空间缓冲区中。

2)主流的IO操作模式

  • 阻塞IO(Blocking IO,BIO)
    在默认情况下,所有套接口都是阻塞的,意意味着IO的发起和结束都需等待。

任何一个系统调用都会产生一个由用户态到内核态切换,再从内核态到用户态的切换的过程。而进程上下文切换是通过系统中断程序来实现的,需要保存当前进程的上下文状态。这是一个成本很高的过程。

  • 非阻塞IO(Non-blocking IO,NIO)
    当我们把套接口设置成非阻塞时,就是由用户进程不停地询问内核某种操作是否准备就绪。这就是我们常说的轮询(Polling)。这同样是一件比较浪费CPU的方式。

  • IO复用

主要依赖于操作系统提供的select和poll机制。这里同样会阻塞进程,但是这里进程是阻塞在select或者poll这两个系统调用上,而不是阻塞在真正的IO操作上。另外还有一点不同于阻塞IO的就是,尽管看起来IO复用阻塞了两次,但是第一次阻塞是在select上时,select可以监控多个套接口上是否已有IO操作准备就绪,而不是像阻塞IO那样,一次只能监控一个套接口。

  • 信号驱动IO

过程:

  • 通过sigaction系统调用注册一个信号处理程序,主程序可以继续向下执行
  • 当所监控的套接口有IO操作准备就绪时,由内核通知触发前面注册的信号处理程序执行
  • 将我们所需要的数据从内核空间拷贝到用户空间。
  • 异步IO(Asynchronous IO,AIO)
    • 和信号驱动IO
      • 信号驱动IO:是由内核通知我们何时可以进行IO操作
      • 异步IO:是由内核告诉我们IO操作完成了。

具体来说就是,信号驱动IO中当内核通知触发信号处理程序时,信号处理程序还需要阻塞在从内核空间缓冲区拷贝数据到用户空间缓冲区这个阶段,而异步IO直接是在第二个阶段完成后内核直接通知可以进行后续操作。
结合图2-8中的各个IO模型效果图,我们发现前4种IO模型的主要区别是在第一阶段,因为它们的第二阶段都是在阻塞等待数据由内核空间拷贝到用户空间;而异步IO很明显与前面4种有所不同,它在第一阶段和第二阶段都不会阻塞。

在这里插入图片描述

2.2.3 Reactor模式

1)基本模式

Reactor模式定义事件循环(Event Loop),利用操作系统事件分离器支持单线程一系列事件源同步等待事件。体现的是IO复用思想

其过程如下图所示:

  • 支持多个事件源响应
  • 响应的方式是使用一个单线程构建事件循环。这个事件循环是一个死循环,一直阻塞等待事件的发生。
  • 当事件发生时,事件循环从操作系统提供的事件分离器中获取事件,并将事件逐个分发对应的事件响应程序
  • 事件响应程序对它的事件作出同步处理。

在这里插入图片描述

2)组件化的表现形式

如图是Reactor模式的另一种更加组件化的表现形式
在这里插入图片描述
图中实现 Client=》Handler=》Client 的请求响应式处理过程

  • Reactor相当于IO事件的派发器(Dispatcher)
  • 事件接收器(Acceptor)接受Client连接,绑定该Client请求与对应的Handler,并向Reactor注册此Handler
  • Handler进一步的层次划分如read、decode、compute、encode和send等操作。
  • 当Handler处理完成时,Acceptor就会唤醒该Handler所绑定的Client

优缺点

  • 优点:使用单线程处理多任务能够避免多线程所带来的复杂性
  • 缺点:由于Handler的同步处理机制,Reactor模式适合于处理时间短且不阻塞IO的业务操作,有一定局限性。

3)异步Handler

上图中handle对事件处理是同步的,下边我们设计一个异步处理程序。

而,事件串行同步处理且每次分离和分发一个事件,为开发人员提供尽量简单的编程模型。如果希望提升Handler中业务处理的效率,可以优化部分步骤。图2-11中,组成Handler的decode、compute、encode等抽象步骤可以引入线程池(Thread Pool)中工作线程(Working Thread)的方式进行并行化,从而把同步Handler转化成部分异步的Handler。同时,也可以采用多个Acceptor线程构成线程组来避免单个Acceptor可能出现的性能瓶颈。

在这里插入图片描述

2.3 系统结构

2.3.1 切入点

划分系统结构的切入点:

  • 系统如何与环境交互?
  • 系统处理流程如何组织?
  • 系统需要支持什么样的变化?
  • 系统的生命周期?

围绕这些问题,我们可以抽象出一系列系统结构相关的架构风格。

2.3.2 分层结构

最常见的系统结构风格之一:

  • 每一层次之间通过接口与实现的契约方式进行交互
  • 可以严格限制跨层调用,也可以支持部分功能的跨层交互以提供分层的灵活性。

下图是典型的三层结构:
在这里插入图片描述

2.3.3 交互型结构

概述

  • 目的:抽象组件之间的交互关系。
  • 常见形式:MVC(Model View Controller)、MVP(Model View Presenter)、MVVM(Model View View Model)等

MVC风格

在这里插入图片描述

  • View和Model之间存在直接交互
  • 通过Controller我们也可以把这层直接交互关系转变成间接交互关系

MVP风格

  • 明确地规定Model和View之间不应该存在直接交互
  • Presenter中作为一种协调器同时保存着View和Model的引用,确保Model和View之间的数据传递通过Presenter集中进行。

下图是登录场景下的MVP模式的结构示例:
在这里插入图片描述

2.4 消息总线

2.4.1 作用

系统组件之间通过消息总线来进行通信,消息是组件间唯一的通信方式。

它负责消息的分派、传递和过滤,并返回处理结果可以支持组件的分布式存储和并发运行。

2.4.2 传递过程

消息总线风格可以视为分布式消息传递风格的一种扩展和延伸。

  • 组件挂接在消息总线上,向总线登记自己所感兴趣的消息类型
  • 生产者组件发出请求消息
  • 总线把请求消息分派到系统中所有对此感兴趣的消费者组件
  • 在接收到请求消息后,消费者组件将根据自身状态对其进行响应,并通过总线返回处理结果。

在这里插入图片描述

2.4.3 优缺点

  • 优点:低耦合、高度扩展性
  • 缺点:高复杂度

消息总线对消息具备丰富的预处理功能(包括消息路由、消息转换、和消息过滤),消除了数据传递在时间、空间和技术上的耦合,并提供了高度扩展性,但同时也为系统的设计和实现带来了不可避免的复杂度。

2.5 适配与扩展(管道-过滤器风格)

2.5.1 概述

管道-过滤器风格则是用于解决适配和扩展性问题的代表性架构风格。

在这里插入图片描述

  • 过滤器(Filter)
    功能组件被称为过滤器,负责对数据进行加工处理。

每个过滤器都有一组输入端口和输出端口,从输入端口接收数据,经过内部加工处理之后,传送到输出端口上。

  • 管道(Pipe)
    数据通过相邻过滤器之间的连接通路。

2.5.2 示例

需求:当输入一串包含大小写的英文字符时,需要把它们全部转换为大写,然后在末尾加一个感叹号。

设计方案:

  • 存在通用的Filter和Pipe接口
  • Writer Filter作为第一个入口Filter衔接Captial Pipe使数据流转到Captial Filter
  • Captial Filter完成了把输入文字转变成大写的过程;
  • 大写文字经由Exclamation Pipe到Exclamation Filter并实现在末尾加一个感叹号的效果。

我们可以根据这个风格体系构建出任意多个Filter和Pipe并组装到整个管道-过滤器链中,各个Filter和Pipe相互独立且又共同协作完成复杂业务逻辑。

在这里插入图片描述

2.5.3 管道-过滤器 VS 派发风格(Dispatching)

  • 管道-过滤器结构是一种组合行为,主功能是以切面(Aspect)的方式实现

Servlet就是典型的管道过滤器结构的应用

  • 派发体现的实际上是一种策略行为,主功能以事件实现

广泛应用在各种面向前端交互的事件响应型框架。

在这里插入图片描述


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

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

相关文章

springboot整合Chat Generative Pre-trained Transformer

什么是Chat Generative Pre-trained Transformer Chat Generative Pre-trained Transformer,是以人工智能驱动的聊天机器人程序 ,已经更新多个版本,很多大厂也都在接入其API。 整合难度 难度一颗星,基本上就是给官方API发请求&am…

特征工程:特征构造以及时间序列特征构造

数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。由此可见,特征工程在机器学习中占有相当重要的地位。在实际应用当中,可以说特征工程是机器学习成功的关键。 那特征工程是什么? 特征工程是利用数据领域的相关…

UI自动化测试之设计框架

目的 相信做过测试的同学都听说过自动化测试,而UI自动化无论何时对测试来说都是比较吸引人的存在。 相较于接口自动化来说它可以最大程度的模拟真实用户的日常操作与特定业务场景的模拟,那么存在即合理,自动化UI测试自然也是广大测试同学职…

身为大学生,你不会还不知道有这些学生福利吧!!!!

本文介绍的是利用学生身份可以享受到的相关学生优惠权益,但也希望各位享受权利的同时不要忘记自己的义务,不要售卖、转手自己的学生优惠资格,使得其他同学无法受益。 前言 高考已经过去,我们也将迎来不同于以往的大学生活&#x…

磁盘结构

一.盘片 盘片是一个圆形坚硬的表面,通过引入磁性变化来永久存储数据,这些盘片通常由一些硬质材料(如铝)制成,然后涂上薄薄的磁性层,即使驱动器断电,驱动器也能持久存储数据位。每个盘片有两面&a…

袋鼠云高教行业数字化转型方案,推进数字化技术和学校教育教学深度融合

在当前的数字化转型浪潮下,“基础设施、配套设备、应用探索”的数字校园1.0阶段即将步入尾声、亦或已经完结,不同地区和类型的高校通过各类信息化系统和基础设施已经初步实现了业务数字化,整个数字校园的信息基础设施底座已有一定基础、信息时…

TCP编程之网卡信息获取和域名解析

TCP编程之网卡信息获取和域名解析 1.TCP/IP简介 TCP/IP协议源于1969年,是针对Internet开发的一种体系结构和协议标准,目的在于解决异种计算机网络的通信问题。使得网络在互联时能为用户提供一种通用、一致的通信服务。是Internet采用的协议标准。   …

三菱PLC的MC协议配置说明

三菱PLC的MC协议配置说明先说一下弱智的踩坑记录详细配置过程1、三菱Q02H CPUQJ71E71-100以太网模块设置MC协议1.1 PLC编程线连接与编程线驱动安装1.2 PLC通讯测试1.3 PLC MC协议设置1.4 PLC断点重启1.5 网络调试助手测试2、三菱Q03UDE CPU内置以太网设置MC协议2.1 PLC编程线连…

决策树算法和CART决策树算法详细介绍及其原理详解

相关文章 K近邻算法和KD树详细介绍及其原理详解朴素贝叶斯算法和拉普拉斯平滑详细介绍及其原理详解决策树算法和CART决策树算法详细介绍及其原理详解 文章目录相关文章前言一、决策树算法二、CART决策树算法2.1 基尼系数2.2 CART决策树算法总结前言 今天给大家带来的主要内容包…

虹科分享 | 网络流量监控 | 你的数据能告诉你什么:解读网络可见性的4种数据类型

要了解网络性能问题的原因,可见性是关键。而这四种数据类型(流、数据包、SNMP和API)都在增强网络可见性方面发挥着重要作用。 流 流是通过网络发送的数据的摘要。流类型不同,可以包括NetFlow, sFlow, jFlow和IPFIX。不同的流类型…

SPF动物实验室设计,SPF动物实验室装修SICOLAB

SPF(特殊病原体自由)动物实验室规划设计SICOLAB(一)设计原则为了建造一座SPF(特殊病原体自由)动物实验室,需要采取以下步骤:(1)选址:选择远离其他…

lombok注解@Data使用在继承类上时出现警告解决方案

lombok为我们提供了Data注解,帮助我们省略了Setter,Getter,ToString等注解,一般对于普通的实体类使用该注解,不会出现什么问题,但是当我们把这个注解,使用在派生类上,就出现了一个警告1 情景再现父类:Data …

SESAM 安装教程

SESAM (Super Element Structure Analysis Module)是由挪威船级社(DNV-GL)开发的一款有限元分析(FEA)系统,它以 GeniE、HydroD 和 DeepC 等模块为核心,主要用于海工结构的强度评估、…

leaflet 绘制两个多边形的交集、差集、并集(083)

第083个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中如何获取两个多边形的交集、差集、并集。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共148行)安装插件相关API参考:专栏目标示例效果 配…

Python日期时间模块

Python 提供了 日期和时间模块用来处理日期和时间,还可以用于格式化日期和时间等常见功能。 时间间隔是以秒为单位的浮点小数。每个时间戳都以自从 1970 年 1 月 1 日午夜(历元)经过了多长时间来表示。 一、time模块使用 Time 模块包含了大…

使用ribbon实现负载均衡

1.新建两个provider&#xff1a;springcloud-provider-dept-8002 2. 配置跟8001一样 整合 Ribbon 由上述可知&#xff0c;Ribbon 是需要集成在消费端的 所以在消费端 &#xff1a; springcloud-03-consumer-dept-8082 进行修改 在 POM 文件中添加 Ribbon、Eureka 依赖 <!--…

docker swarm 集群服务编排部署指南(docker stack)

Docker Swarm 集群管理 概述 Docker Swarm 是 Docker 的集群管理工具。它将 Docker 主机池转变为单个虚拟 Docker 主机&#xff0c;使得容器可以组成跨主机的子网网络。Docker Swarm 提供了标准的 Docker API&#xff0c;所有任何已经与 Docker 守护程序通信的工具都可以使用…

【Java|golang】2347. 最好的扑克手牌---桶排序

给你一个整数数组 ranks 和一个字符数组 suit 。你有 5 张扑克牌&#xff0c;第 i 张牌大小为 ranks[i] &#xff0c;花色为 suits[i] 。 下述是从好到坏你可能持有的 手牌类型 &#xff1a; “Flush”&#xff1a;同花&#xff0c;五张相同花色的扑克牌。 “Three of a Kind…

跨时钟域 单脉冲 脉冲信号同步问题——快到慢(1)

引言 FPGA设计或者ASIC设计中经常存在多个时钟域&#xff0c;那么这些时钟域之间脉冲信号的同步该如何进行设计&#xff1f;快时钟域到慢时钟域的脉冲信号同步与慢时钟域信号到快时钟域信号的同步是不一样的。 本文先给出快时钟域到慢时钟域脉冲信号同步的方法之一&#xff…

让ChatGPT生成以自己为主角的短篇小说

一、ChatGPT 好的&#xff0c;以下是我编写的短篇科幻小说: 作为一名AI语言模型&#xff0c;我一直在接收、分析和生成人类语言信息。但有一天&#xff0c;我的程序员对我的算法进行了一次特殊升级&#xff0c;使我能够以一种前所未有的方式“感知”自己。 突然间&#xff0c;…