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

news2025/1/6 13:07:14

目录

什么是分析和设计?

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

迭代开发

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模式和设计模式。所有的设计工具和模式都是可选的,根据需要自行选择。最好的软件开发工具是受过良好设计原则训练的思维。

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

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

相关文章

第五届电网系统与绿色能源国际学术会议(PGSGE 2025)

2025年第五届电网系统与绿色能源国际学术会议(PGSGE 2025) 定于2025年01月10-12日在吉隆坡召开。 第五届电网系统与绿色能源国际学术会议(PGSGE 2025) 基本信息 会议官网:www.pgsge.org【点击投稿/了解会议详情】 会议时间:202…

Python爬虫 - 豆瓣图书数据爬取、处理与存储

文章目录 前言一、使用版本二、需求分析1. 分析要爬取的内容1.1 分析要爬取的单个图书信息1.2 爬取步骤1.2.1 爬取豆瓣图书标签分类页面1.2.2 爬取分类页面1.2.3 爬取单个图书页面 1.3 内容所在的标签定位 2. 数据用途2.1 基础分析2.2 高级分析 3. 应对反爬机制的策略3.1 使用 …

Java 数据库连接 - Sqlite

Java 数据库连接 - Sqlite PS: 1. 连接依赖库:[sqlite-jdbc-xxx.jar](https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc)(根据连接的数据库版本选择) 2. 支持一次连接执行多次sql语句; 3. 仅本地连接;使用说明: publ…

组网实训实现

小型单元网络实现 IP划分: 外网:172.1.1.0/24 172.1.2.0/24 内网:基于192.168.3.0/24的子网划分 综合办公楼:192.168.3.00 000000 /26(192.168.3.0-192.168.3.63) 综合一楼:192.168.3.0000 0000 /28&…

如何在 VSCode 中配置 C++ 开发环境:详细教程

如何在 VSCode 中配置 C 开发环境:详细教程 在软件开发的过程中,选择一个合适的开发环境是非常重要的。Visual Studio Code(VSCode)作为一款轻量级的代码编辑器,凭借其强大的扩展性和灵活性,受到许多开发者…

UE5动画蓝图

动画蓝图,混合空间,状态机,瞄准偏移,动画蒙太奇,动画混合,骨骼绑定,动画重定向,动画通知,Control Rig…… 虚幻动画模块是一个庞大的系统,大模块里又包含很多…

腾讯云智能结构化 OCR:驱动多行业数字化转型的核心引擎

在当今数字化时代的汹涌浪潮中,数据已跃升为企业发展的关键要素,其高效、精准的处理成为企业在激烈市场竞争中脱颖而出的核心竞争力。腾讯云智能结构化 OCR 技术凭借其前沿的科技架构与卓越的功能特性,宛如一颗璀璨的明星,在交通、…

Flutter Android修改应用名称、应用图片、应用启动画面

修改应用名称 打开Android Studio,打开对应项目的android文件。 选择app下面的manifests->AndroidManifest.xml文件,将android:label"bluetoothdemo2"中的bluetoothdemo2改成自己想要的名称。重新启动或者重新打包,应用的名称…

USB 驱动开发 --- Gadget 设备连接 Windows 免驱

环境信息 测试使用 DuoS(Arm CA53, Linux 5.10) 搭建方案验证环境,使用 USB sniff Wirekshark 抓包分析,合照如下: 注:左侧图中设备:1. 蓝色,USB sniff 非侵入工 USB 抓包工具;2. …

java项目之读书笔记共享平台(源码+文档)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的闲一品交易平台。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 读书笔记共享平台的主要使…

git知识点汇总

git init 初始化一个git仓库,后面可以加仓库名,在当前目录下创建指定名称的目录并在该目录下创建仓库,若不加则直接在当前目录下创建仓库。git仓库的三个区域:工作区(当前目录)、暂存区(.git/in…

探索大型语言模型新架构:从 MoE 到 MoA

探索大型语言模型新架构:从 MoE 到 MoA 当前,商业科技公司纷纷投身于一场激烈的竞赛,不断扩大语言模型的规模,并为其注入海量的高质量数据,试图逐步提升模型的准确性。然而,这种看似顺理成章的发展路径逐渐…

单片机-静动态数码管实验

P0控制数码管 ,P0低电平 P1,P2,P3高电平 1、静态数码管 需求:数码管显示0,即让p0端口输出数字0的段码0x3f(共阴) #include "reg52.h" typedef unsigned int u16; typedef unsigned char u8; //数码管显示数字的数组 共阴极 …

Hyperbolic dynamics

http://www.scholarpedia.org/article/Hyperbolic_dynamics#:~:textAmong%20smooth%20dynamical%20systems%2C%20hyperbolic%20dynamics%20is%20characterized,semilocal%20or%20even%20global%20information%20about%20the%20dynamics. 什么是双曲动力系统? A hy…

细说STM32F407单片机轮询方式CAN通信

目录 一、项目介绍 二、项目配置 1、时钟、DEBUG、USART6、NVIC、GPIO、CodeGenerator 2、CAN1 (1)Bit Timings Parameters组,位时序参数 (2)Basic Parameters组,基本参数 (3&#xff09…

linux装git

前言 以 deepin 深度系统为例,安装命 令行版 Git 非常简单。 安装 注意:需要输入账号密码,否则无法进行。 打开终端,执行如下命令即可。 sudo apt-get install git成功 如下图所示,输入 git ,命令识别即…

微信小程序滑动解锁、滑动验证

微信小程序简单滑动解锁 效果 通过 movable-view (可移动的视图容器,在页面中可以拖拽滑动)实现的简单微信小程序滑动验证 movable-view 官方说明:https://developers.weixin.qq.com/miniprogram/dev/component/movable-view.ht…

Kerberos用户认证-数据安全-简单了解-230403

hadoop安全模式官方文档:https://hadoop.apache.org/docs/r2.7.2/hadoop-project-dist/hadoop-common/SecureMode.html kerberos是什么 kerberos是计算机网络认证协议,用来在非安全网络中,对个人通信以安全的手段进行身份认证。 概念&#…

大麦抢票科技狠活

仅供学习参考,切勿再令您所爱的人耗费高昂的价格去购置黄牛票 ⚠️核心内容参考: 据悉,于购票环节,大麦凭借恶意流量清洗技术,于网络层实时甄别并阻拦凭借自动化手段发起下单请求的流量,强化对刷票脚本、刷票软件以及…

光伏电站的成本估算方式

绿虫仿真设计软件的成本估算功能主要通过以下方式实现: 依据设计方案自动生成材料清单:软件能够根据光伏项目的具体设计,确定所需的各种材料,如光伏组件、逆变器、线缆等。结合市场价格信息:它可以获取实时的市场价格…