面向对象分析和设计OOA/D,UML,GRASP

目录

什么是分析和设计?

什么是面向对象的分析和设计?

迭代开发

UML

用例图

交互图

基于职责驱动设计

GRASP

常见设计原则


什么是分析和设计?

分析,强调是对问题和需求的调查研究,不是解决方案。例如,需要设计一个交易系统,那么如何使用他?他有什么功能?
设计,强调满足需求概念上的解决方案。而不是实现。例如,数据库解决方案和软件对象描述。

什么是面向对象的分析和设计?

面向对象分析(object-oriented analysis):强调的是在问题领域内发现和描述对象或者概念。例如,在学生信息管理系统里包含学生,班级,课程等概念。
面向对象的设计(object-oriented design):强调是定义软件对象以及他们如何协作以实现需求。例如,软件对象学生可以有姓名,学号属性和获取成绩单的的方法。
最后在实现或者面向对象程序设计过程里,会实现设计出来的对象,例如,Student类。
设计对象的交互和职责分配是对象设计的核心。

在oo开发中,至关重要的能力是熟练地为软件对象分配职责。
如何为对象类分配职责?对象之间如何协作?什么样的类应该做什么事情?我们可以使用职责驱动设计,他是一种经典的oo设计。
迭代开发是OOA/D的最佳实践。

迭代开发

迭代开发是指开发被组织成一系列固定的短期的小项目,每次迭代的产品都经过测试,集成并且是可执行局部系统。每次迭代都具有各自的需求分析,设计,实现和测试活动。
迭代的生命周期是经过多次迭代的系统进行持续扩展和精化,并且循环反馈和调整为核心驱动力,最终成为适当的系统。
每次迭代的产品都是最终系统产品的子集。
在迭代的方法里,所有的分析和设计制品(用例文档,uml图),都不是完善的,要根据新发现进行对其进行改进。
保持设计的轻量化和简短,快速进入编码和测试,不要试图在UML模型里细化所有事物。对设计中有创造性和困难的部分进行建模。
在实现过程中的创造和变数,在编程和测试过程中,会出现很多变化并且要发现和解决无数系统问题。只有从软件构造过程中才可以真正发现原本并不知道的需求信息。如果做得好,那么可以将面向对象的设计建模过程中形成的思想和理解作为良好的基础,提高编程的优雅性和健壮性从而应对编程过程中遇到的新问题。但是要对编程过程中的变化和偏差有所预测和计划,这是在迭代开发的关键。

UML

统一建模语言,用来描述,构造和文档化系统产品的可视化语言。UML是图形化表示的标准,用来绘制和展示与软件相关的图形或者文字。他可以便利的帮助我们观察全景,发现软件或者分析之间的联系,同时允许我们忽略细枝末节。
我们不需要为所有的场景绘制UML图形,只需要为在架构上重要的或者有风险的场景创建。
我们可以使用IDE提供的逆向工程从代码生成图形。这样可以作为可视化学习的辅助工具从而有助于理解现有代码。

用例图

什么是用例?
用例是文本形式的情景描述,用来说明参与者使用系统以实现某些目标。用例就是需求,主要用来说明系统如何工作的功能性或行为性需求。
用例,

21点游戏规则

游戏的目标是获得点数最接近或等于21点的手牌。
胜利者需要赢过庄家的手牌并且不能超过21点。
无论桌上有几名玩家,总是和庄家论输赢。
在21点游戏里,2~10的牌的点数就是牌面的数值,A的点数根据玩家的需要可以取1或11点,JQK的点数都是10。
游戏开始时,玩家首先下注,下注的额度是有上限的。
如果你是唯一的玩家,下注后,庄家给你发2张牌,牌面向上,双方都能看到。
庄家给自己发两张牌,一张向上叫明牌,一张向下的叫底牌。
如果有多个玩家,则庄家给每位玩家都是先发一张明牌,庄家给自己发一张底牌,再给每一位玩家和庄家各发一张明牌。
发完两张牌之后,每位玩家自己决定是否要跟多的牌,当对手的牌数满意之后,就停手等待。
停手等待之后,庄家开始加牌,但是不能超过21点。
当你的手牌超过庄家时你赢,当你的手牌点数不及庄家时,庄家赢。
玩家赢,你的手牌超过庄家,并且不能超过21点,或者庄家超过21点。
玩家输,玩家超过21点。

场景,
庄家                                                                        玩家
庄家洗牌                                                                 玩家下注
庄家给自己发牌                                                      玩家拿牌到手里
手牌返回庄家手牌点数                                           手牌返回玩家手牌点数
庄家发第二张牌                                                      玩家继续要牌
庄家问玩家是否继续要牌                                        玩家拿牌到手里
庄家询问玩家手牌点数                                           手牌返回玩家手牌点数
庄家亮牌                                                                 玩家增加或减少赌注
庄家分配赌金                                                          玩家亮牌

使用21游戏作为例子,使用CRC分拣方法得到游戏相关卡片

21点游戏CRC卡

CRC分拣法参考:CRC卡片分拣法,CRC建模,CRC模型icon-default.png?t=O83Ahttps://mp.csdn.net/mp_blog/creation/editor/144721896使用CRC卡片分拣法把用例文档分析一遍之后,我们可以很容易绘制用例图,类图,然后把注意力放在序列图上,在绘制序列图时决定类的职责分配。

什么是用例图?
用来描述用例名称和参与者之间的关系,为系统提供简洁可视化的语境图或环境图。用例图能够表示系统边界和边界之外的事物以及系统如何使用。可以用作沟通工具,用以概况系统和参与者的行为。
什么是参与者?
参与者是在我们讨论的系统里调用其他系统服务的时候,任何具有行为的事物。可以是人,组织,软件和计算机。例如,玩家和庄家。

领域模型

领域模型是对领域内的概念类或者真实世界中对象的可视化表示。在UML里领域模型是一组没有定义操作的类图。他可以展示,1.领域对象或者概念类2.概念类之间的关系3.概念类的属性。
领域模型不是软件对象,不包含对象的职责。
为什么使用领域模型?
使用领域模型可以帮助我们理解需求中的概念的和词汇。软件类的名词要源于领域模型中的名称,方便使对象具有领域的信息和职责。这样做可以减小我们的思维和软件对象之间的表示差异。

如何创建领域模型?
1.寻找概念类。
2.把概念类绘制成UML类图。
3.添加关联关系和属性。

怎么寻找概念类?
使用CRC模型。

什么是关联?
关联是类的实例之间的关系,表示有意义和值的关注的连接。是否需要关联基于现实世界的需要。添加关联是为了突出我们对于重要关系的大致理解,而不是记录对象或者数据。
关联的命名规则
以类名-动词短语-类名的格式为管理命名,其中的动词短语构成了可读的和用意义的顺序。
角色
关联的每一端称为角色,角色具有以下可选项,
多重性表达式,定义了类A有多少个实例可以和类B的一个实例关联。例如一个手牌实例和多个牌实例关联。
属性
属性是对象的逻辑数组。例如,牌含有点数,牌面数值。
在领域模型里的属性应该是简单的数据类型,通过关联来表示概念类之间的关系而不是属性。
导出属性
例如,Hand的value可以从Card的信息里推导处来。在属性名加"/"来表示
属性的表示方法
可见性符号 属性名称:属性类型=[默认值](可选)
可见性符号,
+公共属性
-私有属性
#保护属性
~包属性

21点游戏概念图

系统序列图
系统序列图是用来表示外部参与者到系统相关的io事件。他是操作契约和对象设计的输入。对于用例的一个特定场景,外部参与者产生的事件,其顺序和系统之内的事件。所以系统被视为黑盒,系统序列图强调的是从参与者到系统的跨越系统边界的事件。
为什么使用系统序列图?
系统需要处理和响应来自参与者的外部事件,时间事件,错误和异常,因此需要准确的知道,什么是外部输入的事件,即系统事件。这些事件是系统分析的重要部分。在对软件应该将如何工作进行详细设计之前,我们系统的行为作为黑盒来调查和定义。将用例隐含的交互可视化。
系统行为描述系统做什么,而不是解释如何去做。

交互图

交互图可以用来动态对象建模,他有2种类型:序列图和通信图。在画交互图的时候考虑和决定职责的分配。
什么是动态对象建模?
在设计对象的过程里,需要哪些对象,他们如何通过消息和方法进行协作,在画交互图的过程中把对象之间的协作方式确定下来。动态对象建模有助于设计逻辑和代码的行为。

序列图以一种栅栏格式描述交互,在右侧添加新创建的对象。使用序列图可以方便的表达调用流的顺序,只需要从上到下阅读即可。
使用生命线表示参与者。
消息,在垂直的生命线之间,用带实心箭头的实线并附加消息表达式的方式表示对象之间的每个消息。
消息表达式的语法:return = message(parameter:parameterType:returnType),没有参数时可以省略括号。例如,size = getDeckSize()

在序列图里的图形框,图形框包含下列操作符
alt        选择性片段,表示有互斥条件的消息
loop     表示消息为真时的循环片段
opt       当消息为真时执行的片段
par       并行执行的消息片段

通信图以图或者网络格式描述对象的交互,其中对象可以置于图中的任何位置。

类图

类图表示类,接口及其关联。类图用于静态对象建模。与领域模型相比类图增加了属性的类型和方法。set,get方法通常省略不表。
常见类之间的关系如下所示,
泛化(继承)关系,用由子类到超类的实线和空心三角箭头表示。
依赖关系,用从客户到提供者的虚线箭头表示。
什么时候表示依赖关系?
使用依赖线描述对象之间的参数变量,局部变量和静态方法的依赖。
组合关系,表示整体和部分的组成关系。例如,房间必须有门和窗户组成。用带有实心菱形箭头的关联线来表示。

基于职责驱动设计

基于职责驱动设计(RDD)的内在含义是考虑怎样给协作中的对象分配职责、角色和协作。在RDD里认为对象具有职责,即对其所作所为的抽象。
职责分为2种类型:行为和认知
对象的行为职责,
自身执行一些行为,例如,创建对象或者计算。
初始化其他对象中的操作。
控制和协调其他对象中的活动。
例如,庄家负责有洗牌的职责。
对象的认知职责,
对私有封装数据的认知。
对相关对象的认知
对其能够导出或计算的事物的认知。
手牌负责认知牌的总点数。
职责的粒度,大粒度职责具有数百个类和方法。例如,DataSource的职责可能涉及系统中几百个类和几千方法。小粒度职责可能只是一个方法。例如,创建牌的职责可能只涉及一个类中的一个方法。
职责是一种抽象,方法实现职责。职责借助与方法实现,这个方法可以独立完成,也可以与其他方法和对象协作完成。例如,庄家类定义方法来洗牌,也可以将洗牌操作通知一幅牌来完成。

RDD把软件对象想成具有某种职责的人,他可以自己独立完成工作,也可以和同事分工合作一起完成工作。RDD使我们把面向对象的设计看作是有职责对象进行协作的共同体。

GRASP

GRASP是通用职责分配软件模式,General Responsibility Assignment Software Patterns。他是一种学习工具,能够帮助开发人员理解基本对象的设计,并且以一种系统的,合理的,可以解释的方式运用设计推理。

GRASP有9个模式,
创建者
控制器
纯虚构
信息专家
高内聚
低耦合
间接性
多态性
保护变化

创建者,
谁负责创建类的新实例?
如果以下的条件为真(越多越好),则将创建类A的实例的职责分配给类B
B包含或者组成A
B记录A
B使用A
B具有A的初始化数据,并且在创建A时会将这些数据传递给A。
例如,在21点游戏里一副牌负责创建牌对象。

信息专家,
给对象分配职责的基本原则是什么?
把职责分配给具有完成这个职责所需要信息的那个类。
信息专家是最基本的职责分配原则之一。履行职责需要满足完成职责所需要信息,即关于其他对象的信息,对象自身的状态,对象周围的环境,对象能够推导出的信息等。信息专家支持低耦合,信息专家使我们寻找到的对象具有职责所需要的大部分信息,并且把职责分配给这个对象。如果我们职责分配给其他对象,那么总体的耦合度就会增高,因为存在更多的信息被某些事物所分享,而且这些事物远离信息源。例如,玩家需要知道手牌的点数是多少,那么把计算总点数的职责交给手牌,因为手牌拥有牌的集合信息。
如果有多个局部信息对象有待选择的时候,将职责赋予具有支配作用的信息专家,即持有主要信息的对象,这样有助于保持低耦合。
当存在多个选择时,考虑每个选择对耦合和内聚的影响,由此选择最佳方案。
如果还是无法选出,则要考虑软件对象在未来可能的进化以及信息专家,耦合和内聚的影响。

低耦合,
如何减少因为变化产生的影响,降低依赖和提高可重用性?
分配职责使耦合保持在较低水平。低耦合是一个需要不断考虑的基本原则。我们使用低耦合来评价现有设计,和新的可选方案之间作出选择,应该首选耦合度更低的方案。
什么是耦合?
耦合是元素与其他元素的连接,感知以及依赖的程度的度量。具有低耦合的类不会过度的依赖其他的类。如果存在耦合关系,那么当被依赖的元素发生变化时,则依赖者也会受到影响。对象之间适当的耦合对系统来说正常和必要的,其中的任务是通过被连接对象之间的协作来完成。例如,子类和父类就是强耦合关系。高耦合对于稳定和普遍使用的元素不是问题,例如,Java程序可以安全和Java类库耦合,因为Java库是稳定,普遍使用的。高耦合本身不是问题,问题是与某些不稳定的元素之间的耦合,例如,不稳定接口和实现。我们需要关注实际当中极其不稳定或需求经常发生变化的地方。

为什么要使用低耦合?
因为低耦合能够减少修改软件所需要的时间,工作量和缺陷。

高内聚
怎样保持对象是有重点或者聚焦,可以理解,可管理的,并且能够支持低耦合?
内聚是指功能内聚,是对元素职责的相关性和集中度的度量。分配职责时保持较高的内聚性。内聚性较低的类需要做许多不相关的工作,或者需要完成大量工作。这样的类是不合理的,他们是难以理解,难以复用,难以维护的,也是脆弱的,经常会收到变化的影响。低内聚表示了大粒度的抽象或者承担了本应该委托给其他对象的职责。高内聚是一个需要不断考虑的基本原则。例如,一个人承担了太多的不相关的工作,特别是应该委托给别人的工作,那么这个人一定没有很高的工作效率。

控制器,
在UI层之上首先接收和控制系统的操作对象是什么?
把职责分配给下列对象
代表全部系统,根对象,运行软件设备或者主要子系统。例如,外观模式。
代表发生系统操作的用例场景。例如,springMVC里controller用来接收请求和返回响应。从请求里获取信息封装成pojo,然后把工作委托给业务层,再把业务层的处理结果放入响应里。
控制器自己不完成工作,把系统操作的职责委托给应用层或者领域层中的对象。控制器增加可复用和可插拔的能力。UI层不处理系统操作,只是把事件委托给其他层处理。

多态性
如何处理基于类型的选择?如何创建可插拔的软件组件?
基于类型的选择,条件变化是程序的一个基本主题。如果使用if-else或者case语句的条件逻辑来设计程序,那么当出现新的变化时,就需要修改这些条件逻辑。这种方法很难扩展新变化的程序,因为需要修改多个地方。
可插拔软件构件,客户-服务器关系里的可视化组件,如何才能替换服务组件而不会对客户端产生影响?
当选择或者行为随着类型有所不同时,使用多态操作为变化的行为的类分配职责。不要测试对象的类型,也不要使用条件逻辑来执行基于类型的不同选择。这样可以易于增加新变化所需的扩展,无需影响客户便能够引入新的实现。

纯虚构
当你并不想违背高内聚和低耦合或者其他目标,但是基于信息专家所提供的方案又不合适时,哪些对象应该承担这样的职责?
面向对象设计有时被描述为,实现软件类,使其表示真实世界问题领域的概念,以降低表示差异,例如,玩家和庄家,然而,在很多情况下,只对领域对象分配职责会导致不良内聚或者耦合,或者降低复用能力。
用人为制造出来的类给他分配一组高内聚的职责,该类并不表示问题领域的概念,他是虚构的事物,用来支持高内聚,低耦合和复用。例如userDao对象,用来和数据库交互查询和保存对象。这样的对象是无法再领域模型里找到这个名称或者持久性存储的概念。他是为了软件开发而创造出来的概念。
纯虚构通常基于相关功能性进行划分,因为这是一种以功能或者行为为中心的对象。例如,适配器,命令,策略等模式。

间接性
为了避免多个事务之间的直接耦合,应该如何分配职责?如何使对象解耦,以支持低耦合并且提高复用潜力?
将职责分配给中介对象,使其作为其他构建或服务之间的媒介,以避免他们之间的直接耦合。中介实现了其他构件之间的间接性。计算机科学里的大多数问题都可以通过增加一层间接性来解决。例如,适配器,外观,观察者模式。

保护变化(protected variations),
怎么样设计对象、系统和子系统,使他的内部的变化不会对其他元素产生不良影响?
找出或识别出预期的变化,然后在这些变化之外通过分配职责来创建稳定的接口。也就是说,把程序中不稳定部分的程序包裹在接口内,利用多态来产生此一接口的不同实现。
例如,数据封装,接口,多态,间接性,模型视图分离原则,观察者模式这些技巧都是用来保护变化。

常见设计原则

模型-视图分离原则
模型对象不应该直接与视图对象交互。

模块化设计
模块化是将系统分解为一组内聚的,松耦合的模块的特性,也就是说,通过创建高内聚,低耦合的的方法和类来实现模块化。

命令-查询分离原则
一个方法不能同时属于以下2种类型
执行动作的命令方法,具有改变对象状态的副作用,并且是没有返回值的。
查询数据的方法,没有副作用,不会改变任何对象的状态。

面向对象的设计涉及一系列柔性原则,自由度很大,这反应了设计工作的复杂性。在设计过程里并行和互补地创建动态和静态对象模型,也就是说同时绘制序列图和类图来反应设计决策。并且在绘制过过程中运用GRASP模式和设计模式。所有的设计工具和模式都是可选的,根据需要自行选择。最好的软件开发工具是受过良好设计原则训练的思维。

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

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

相关文章

MySQL使用navicat新增触发器

找到要新增触发器的表,然后点击设计,找到触发器标签。 根据实际需要,填写相关内容,操作完毕,点击保存按钮。 在右侧的预览界面,可以看到新生成的触发器脚本

Anthropic 的人工智能 Claude 表现优于 ChatGPT

在人工智能领域,竞争一直激烈,尤其是在自然语言处理(NLP)技术的发展中,多个公司都在争夺市场的主导地位。OpenAI的ChatGPT和Anthropic的Claude是目前最具影响力的两款对话型AI产品,它们都能够理解并生成自然…

《罪恶装备-奋战》官方中文学习版

《罪恶装备 -奋战-》是Arc System Works开发的格斗游戏《罪恶装备》系列的第二十五部作品 [1],男主角索尔历时25年的故事就此画上句号,而罪恶装备的故事却并未结束。 《罪恶装备-奋战》官方中文版 https://pan.xunlei.com/s/VODWAm1Dv-ZWVvvmUMflgbbxA1…

期末概率论总结提纲(仅适用于本校,看文中说明)

文章目录 说明A选择题1.硬币2.两个事件的关系 与或非3.概率和为14.概率密度 均匀分布5.联合分布率求未知参数6.联合分布率求未知参数7.什么是统计量(记忆即可)8.矩估计量9.117页12题10.显著水平阿尔法(背公式就完了) 判断题11.事件…

流程图(四)利用python绘制漏斗图

流程图(四)利用python绘制漏斗图 漏斗图(Funnel Chart)简介 漏斗图经常用于展示生产经营各环节的关键数值变化,以较高的头部开始,较低的底部结束,可视化呈现各环节的转化效率与变动大小。一般重…

继承(5)

大家好,今天我们继续来学习继承的相关知识,来看看子类构造方法(也叫做构造器)是如何做的。 1.6 子类构造方法 父子父子,先有父再有子,即:子类对象构选时,需要先调用基类构造方法,然后执行子类的构造方法 ★此时虽然执行了父类的…

Vue框架主要用来做什么?Vue框架的好处和特性.

在快速发展的互联网时代,前端开发技术的变革日新月异,为开发者带来了前所未有的机遇与挑战。Vue.js,作为前端开发领域的一颗璀璨新星,以其轻量级、高效灵活的特性,赢得了广大开发者的青睐。本文将深入探讨Vue框架的主要…

搭建Hadoop分布式集群

软件和操作系统版本 Hadoop框架是采用Java语言编写,需要java环境(jvm) JDK版本:JDK8版本 ,本次使用的是 Java: jdk-8u431-linux-x64.tar.gz Hadoop: hadoop-3.3.6.tar.gz 三台Linux虚拟节点: CentOS-7-x86_64-DVD-2…

电子应用设计方案87:智能AI收纳箱系统设计

智能 AI 收纳箱系统设计 一、引言 智能 AI 收纳箱系统旨在为用户提供更高效、便捷和智能的物品收纳与管理解决方案,通过融合人工智能技术和创新设计,提升用户的生活品质和物品整理效率。 二、系统概述 1. 系统目标 - 实现物品的自动分类和整理&#xf…

MySQL数据结构选择

系列文章目录 一、MySQL数据结构选择 二、MySQL性能优化explain关键字详解 三、MySQL索引优化 文章目录 系列文章目录前言一、索引1.1、什么是索引1.2、构建索引的过程1.3、索引的更新和维护1.4、索引的查询和管理1.5、InnoDB 和 MyISAM 的索引实现1.6、联合索引和最左前缀法则…

shell基础使用及vim的常用快捷键

一、shell简介 参考博文1 参考博文2——shell语法及应用 参考博文3——vi的使用 在linux中有很多类型的shell,不同的shell具备不同的功能,shell还决定了脚本中函数的语法,Linux中默认的shell是 / b in/ b a s h ,流行的shell…

(leetcode算法题)76. 最小覆盖子串

以s "ADOBECODEBANC", t "ABC"为例,进行如下演示 对于上图的说明: 1. 上面八个状态是在从左往右滑动窗口时,每发现一个窗口满足以下条件就进行状态暂停 条件:s[l, r] 覆盖了 t 这个字符串 2. 只有出窗口之…

二、BIO、NIO编程与直接内存、零拷贝

一、网络通信 1、什么是socket? Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口,一般由操作 系统提供。客户端连接上一个服务端,就会在客户端中产生一个 socket 接口实例,服务端每接受 一个客户端…

HDFS架构原理

一、HDFS架构整体概述 HDFS是Hadoop Distribute File System 的简称,意为:Hadoop分布式文件系统。HDFS是Hadoop核心组件之一,作为大数据生态圈最底层的分布式存储服务而存在。HDFS解决的问题就是大数据如何存储,它是横跨在多台计算机上的文件…

Qt项目打包成绿色软件

Qt项目打包成绿色软件 一、图标添加与配置二、编译后打包文件附录有朋友将程序发给别人后运行,发现各种问题,如: 1.无法定位程序输入点__cxa_thread_atexit于动态链接库…。 2.缺少各种**.dll文件。 问‌我运行环境上Microsoft Visual C++ Redistributable运行环境都有,版本…

自动驾驶相关知识学习笔记

一、概要 因为想知道SIL、HIL是什么仿真工具,故而浏览了自动驾驶相关的知识。 资料来源《自动驾驶——人工智能理论与实践》胡波 林青 陈强 著;出版时间:2023年3月 二、图像的分类、分割与检测任务区别 如图所示,这些更高阶的…

C# 之某度协议登录,JS逆向,手机号绑定,获取CK

.NET兼职社区 .NET兼职社区 .NET兼职社区 .NET兼职社区 有需要指导,请私信我留言V或者去社区找客服。

数值分析速成复习笔记

请确保你有10hour的有效学习时间,保你拿90 证明部分 编程部分

06-RabbitMQ基础

目录 1.初识MQ 1.1.同步调用 1.2.异步调用 1.3.技术选型 2.RabbitMQ 2.1.安装 2.2.收发消息 2.2.1.交换机 2.2.2.队列 2.2.3.绑定关系 2.2.4.发送消息 2.3.数据隔离 2.3.1.用户管理 2.3.2.virtual host 3.SpringAMQP 3.1.导入Demo工程 3.2.快速入门 3.2.1.消…

Ungoogled Chromium127 编译指南 MacOS 篇(二)- 项目要求

1. 引言 在开始编译 Ungoogled Chromium 之前,我们需要确保系统满足所有必要的硬件和软件要求。由于浏览器编译是一个资源密集型的任务,合适的硬件配置和完整的软件环境至关重要。本文将详细介绍编译 Ungoogled Chromium 所需的各项要求。 2. 硬件要求…