版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第3章经典软件体系结构风格《软件体系结构与设计实用教程》第二版3.1调用-返回风格3.1.1主程序-子程序风格结构化方法设计思路:自顶向下、逐步求精。采用模块分解与功能抽象,自顶向下、分而治之程序结构:按功能划分为若干个基本模块,形成一个树状结构各模块间的关系尽可能简单,功能上相对独立;每一模块内部均是由顺序、选择和循环三种基本结构组成其模块化实现的具体方法是使用函数(子程序)主程序-子过程风格的基本构成组件主程序、子程序连接件调用-返回机制拓扑结构层次化结构本质:将大系统分解为若干模块(模块化),主程序调用这些模块实现完整的系统功能。voidmain(){printstar();printmessage();}例#include<stdio.h>voidprintstar(){printf(“*************\n”);}voidprintmessage(){printf(“Hello,world.\n”);printstar();}组件主程序main()子程序printstar()和printmessage()连接件主程序main()调用子程序printstar()和printmessage()因为没有参数的传递,所以比较简单。含有参数的子程序的一般调用过程如下。按从右到左的顺序,计算实参各表达式的值;按照位置,将实参的值一一传给形参;执行被调用函数(子程序);当遇到return(表达式)语句时,计算表达式的值,并返回主调函数(主程序)。函数参数和函数的值——调用返回机制例#include<stdio.h>intmax(intx,inty){intz;z=x>y?x:y;return(z);}voidmain(){inta,b,c;scanf(“%d,%d”,&a,&b);c=max(a,b);printf(“Themaxis%d”,);}组件主程序main()函数子程序max(a,b)函数;连接件main()函数中调用max(a,b)函数,max()函数将实参a、b分别传递给虚参x、y,通过运算得到较大值z,并将z返回调用处,赋值给main()函数的变量c。主程序-子过程风格的优点与缺点优点:有效地将一个较复杂的程序系统设计任务分解成许多易于控制和处理的子任务,便于开发和维护已被证明是成功的设计方法,可以被用于较大程序主程序-子过程风格的优点与缺点缺点:规模:程序超过10万行,表现不好
;程序太大,开发太慢,测试越来越困难可重用性差、数据安全性差,难以开发大型软件和图形界面的应用软件把数据和处理数据的过程分离为相互独立的实体,当数据结构改变时,所有相关的处理过程都要进行相应的修改图形用户界面的应用程序,很难用过程来描述和实现,开发和维护也都很困难。3.1.2面向对象风格OO风格基本构成组件对象,或者说是抽象数据类型(类)的实例类连接件对象是通过函数和过程的调用-返回机制来交互的类通过定义对象,再采用调用调用-返回机制进行交互classSpot{privateintx,y;Spot(intu,intv){setX(u);setY(v);}voidsetX(intx1){x=x1;}voidsetY(inty1){y=y1;}intgetX(){returnx;}intgetY(){returny;}}classTrans{voidmove(Spotp,inth,intk){p.setX(p.getX()+h);p.setY(p.getY()+k);}}classTest{publicstaticvoidmain(Stringargs[]){Spots=newSpot(2,3);System.out.println("s点的坐标:"+s.getX()+","+s.getY());Transts=newTrans();ts.move(s,4,5);System.out.println("s点的坐标:"+s.getX()+","+s.getY());}}组件Spot、Trans、Test三个类Spot的对象s,Trans的对象ts。连接件如下在Test类里面创建Spot类的对象s、Trans类的对象ts,Trans类的move()方法的参数里面有Spot类的对象p。Test类使用Spot类的对象s,调用了Spot类的getX()和getY()方法;Test类使用Trans类的对象ts,调用了Trans类move()方法,并把实参Spot类的对象s传递给了虚参Spot类的对象p。OO特性抽象封装:限制对某些信息的访问多态:在运行时选择具体的操作继承:对共享的功能保持唯一的接口交互:通过过程调用或类似的协议动态绑定:运行时决定实际调用的操作复用和维护OO风格优点复用和维护:利用封装和聚合提高生产力因为对象对其它对象隐藏它的表示,所以可以改变一个对象的表示,而不影响其它的对象。某一组件的算法与数据结构的修改不会影响其他组件组件之间依赖性降低,提高了复用度反映现实世界容易分解一个系统设计者可将一些数据存取操作的问题分解成一些交互的代理程序的集合OO风格缺点管理大量的对象:怎样确立大量对象的结构继承引起复杂度,关键系统中慎用必须知道对象的身份为了使一个对象和另一个对象通过过程调用等进行交互,必须知道对象的标识。只要一个对象的标识改变了,就必须修改所有其他明确显式调用它的对象,并消除由此带来的一些副作用(例如,如果A使用了对象B,C也使用了对象B,那么,C对B的使用所造成的对A的影响可能是料想不到的)对比:在管道-过滤器系统中,一个过滤器无需知道其他过滤器的任何信息不是特别适合功能的扩展。为了增加新功能,要么修改已有的模块,要么就加入新的模块,从而影响性能3.2数据流风格3.2.1数据流体系结构风格的基本特征数据流风格由数据控制计算系统结构由数据在处理之间的有序移动决定数据流系统的结构是显而易见的在纯数据流系统中,处理之间除了数据交换,没有任何其他的交互一个直观实例:在MSExcel中,改变某个单元格的值,则依赖于该单元格的其他单元格的值也会随之改变。三种典型的数据流风格批处理管道-过滤器过程控制,3.73.2.1批处理风格每个处理步骤是一个独立的程序每一步必须在前一步结束后才能开始数据必须是完整的,以整体的方式传递典型应用:传统的数据处理程序编译/CASE(computeraidedsoftwareengineering)工具
批处理风格-基本构成基本组件独立的应用程序连接件某种类型的媒质(magnetic
tape)表达拓扑结构连接件定义了相应的数据流图每一步骤必须在前一步骤完全结束之后方能开始程序1将一批数据以二进制形式存放在磁盘文件中。#include<fstream>usingnamespacestd;structstudent{charname[20];intnum;intage;charsex;};intmain(){studentstud[3]={"Li",1001,18,'f',"Fun",1002,19,'m',"Wang",1004,17,'f'};ofstreamoutfile("stud.dat",ios::binary);if(!outfile){cerr<<"openerror!"<<endl;abort();//退出程序
}for(inti=0;i<3;i++)outfile.write((char*)&stud[i],sizeof(stud[i]));outfile.close();return0;}程序2将刚才以二进制形式存放在磁盘文件中的数据读入内存并在显示器上显示。#include<fstream>usingnamespacestd;structstudent{stringname;intnum;intage;charsex;};intmain(){studentstud[3];inti;ifstreaminfile("stud.dat",ios::binary);if(!infile){cerr<<"openerror!"<<endl;abort();}for(i=0;i<3;i++)infile.read((char*)&stud[i],sizeof(stud[i]));infile.close();for(i=0;i<3;i++){cout<<"NO."<<i+1<<endl;cout<<"name:"<<stud[i].name<<endl;cout<<"num:"<<stud[i].num<<endl;;cout<<"age:"<<stud[i].age<<endl;cout<<"sex:"<<stud[i].sex<<endl<<endl;}return0;}组件程序1程序2连接件文件stud.dat第一个java文件importjava.io.BufferedInputStream;importjava.io.DataInputStream;importjava.io.FileNotFoundException;importjava.io.FileInputStream;importjava.io.IOException;publicclassreceiver{FiletempFile=newFile("Data.dat");if(tempFile.exists()){System.out.println("文件Data.dat已经存在!");System.exit(0);}publicvoidgetNumber(){DataInputStreamin=null;try{in=newDataInputStream(newBufferedInputStream(newFileInputStream(tempFile)));}catch(FileNotFoundExceptione){e.printStackTrace();}for(inti=0;i<6;i++)try{ System.out.print(""+in.readInt());}catch(IOExceptione){e.printStackTrace();}if(in!=null){try{ in.close();}catch(IOExceptione){e.printStackTrace();}}} }第二个java文件importjava.io.BufferedOutputStream;importjava.io.DataOutputStream;importjava.io.FileNotFoundException;importjava.io.FileOutputStream;importjava.io.IOException;publicclasssender{FiletempFile=newFile("Data.dat");if(tempFile.exists()){System.out.println("文件Data.dat已经存在!");System.exit(0);}publicvoidoutNumber(){DataOutputStreamout=null;try{out=newDataOutputStream(newBufferedOutputStream(newFileOutputStream(tempFile)));}catch(FileNotFoundExceptione){e.printStackTrace();}for(inti=0;i<6;i++)try{out.writeInt((int)(Math.random()*100));}catch(IOExceptione){e.printStackTrace();}if(out!=null) {try{out.close();}catch(IOExceptione){e.printStackTrace();}}} }组件receiver程序sender程序;连接件文件Data.datsender程序,使用File类判断当前目录中是否已存在文件Data.dat,如存在,则中断程序的运行,否则继续;然后使用DataOutputStream及相关IO流类将随机产生的6个整数存入数据文件Data.dat;receiver程序,使用DataInputStream及相关IO流类从Data.dat文件中读取数据,并在屏幕上显示出来。3.2.2管道与过滤器风格管道过滤器风格的基本构成(1)组件:过滤器,处理数据流一个过滤器封装了一个处理步骤数据源点和数据终止点可以看作是特殊的过滤器过滤器对输入流进行处理、转换,处理后的结果在输出端流出。每个组件都有输入/输出集合,组件在输入处读取数据流,经过内部处理,在输出处生成数据流。管道过滤器风格的基本构成(2)连接件:管道,连接一个源和一个目的过滤器转发数据流数据可能是ASCII字符形成的流连接件位于过滤器之间,起到信息流的导管的作用,被称为管道。连接件就象是数据流传输的管道,将一个过滤器的输出传到另一过滤器的输入。管道只是对数据传输的抽象,它可能是管道,也可能是其它通信方式,甚至什么都没有(所有过滤器都在原始数据基础上进行处理)
管道过滤器风格的基本构成(3)拓扑结构:连接器定义了数据流图管道-过滤器风格的优点(一)由于每个组件的行为不受其他组件的影响,整个系统的行为易于理解系统中的组件具有良好的隐蔽性和高内聚、低耦合的特点支持软件复用:允许设计者将整个系统的输入/输出行为看成是多个过滤器的行为的简单合成;只要提供适合在两个过滤器之间传送的数据,任何两个过滤器都可被连接起来;系统维护和增强系统性能简单:新的过滤器可以添加到现有系统中来,旧的可以被改进的过滤器替换掉;管道-过滤器风格的优点(二)允许对一些如吞吐量、死锁等属性的分析;支持并行执行:每个过滤器是作为一个单独的任务完成,因此可与其它任务并行执行。管道-过滤器风格的缺点(一)通常导致进程成为批处理的结构这是因为虽然过滤器可增量式地处理数据,但它们是独立的,所以设计者必须将每个过滤器看成一个完整的从输入到输出的转换;不适合处理交互的应用当需要增量地显示改变时,这个问题尤为严重;管道-过滤器风格的缺点(二)在数据传输上没有通用的标准,每个过滤器都增加了解析和合成数据的工作,这样就导致了系统性能下降,并增加了编写过滤器的复杂性。
绝大部分处理时间消耗在格式转换上(需要对数据传输进行特定的处理时,会导致对于每个过滤器的解析输入和格式化输出要做更多的工作,带来系统复杂性的上升)批处理与管道-过滤器的比较相似点:把任务分解成为一系列固定顺序的计算单元
彼此间只通过数据传递交互批处理与管道-过滤器的比较不同点:BatchSequentialPipe-and-Filter整体传递数据组件粒度较大延迟高,实时性差无并发增量组件粒度较小实时性好可并发管道-过滤器风格的例子:DOSDOS中也有管道命令。DOS允许在命令中出现用竖线字符“|”分开的多个命令,将符号“|”前面的命令的输出,作为“|”之后命令的输入,这就是“管道功能”,竖线字符“|”就是管道操作符。例如,命令“dir|more”使得当前目录列表在屏幕上逐屏显示。dir的输出的是整个目录列表,它不出现在屏幕上而是由于符号“|”的规定,成为下一个命令more的输入,more命令则将其输入一屏一屏地显示,成为命令行的输出。Java管道流JavaI/O流中的管道流类PipedInputStream和PipedOutputStream可以方便地实现管道-过滤器体系结构,这两个类的实例对象要通过connect方法连接。JavaI/O流中有管道流类PipedInputStream、PipedOutputStream和PipedReader、PipedWriter,它们的对象总是成对出现。写入类PipedOutputStream的对象的数据,可以由与之相连接的类PipedInputStream的对象读出;写入类PipedWriter的对象的数据,可以由与之相连接的类PipedReader的对象读出。可见,这两组管道流类与管道组件的要求相吻合,可以借助它们实现管道。所以,使用它们,可以方便地实现管道-过滤器体系结构。这两个类的实例对象通过connect()方法连接。Java管道流下面程序的功能是sender发送“Hello,receiver!I`msender”给receiver,然后receiver接受后显示出来并且在前面加上“thefollowingisfromsender”的信息。管道流内部在实现时还有大量的对同步数据的处理,管道输出流和管道输入流执行时不能互相阻塞,所以一般要开启独立线程分别执行,顺便复习了多线程操作。importjava.io.*;importjava.util.*;publicclassTestPiped{publicstaticvoidmain(String[]args){senders=newsender();receiverr=newreceiver();PipedOutputStreamout=s.getOut();PipedInputStreamin=r.getIn();try{in.connect(out);s.start();r.start();}catch(Exceptione){e.printStackTrace();}}}classsenderextendsThread{PipedOutputStreamout=newPipedOutputStream();publicPipedOutputStreamgetOut(){returnout;}publicvoidrun(){Stringstr="Hello,receiver!I`msender\n";try{out.write(str.getBytes());out.close();}catch(Exceptione){e.printStackTrace();}}}classreceiverextendsThread{PipedInputStreamin=newPipedInputStream();publicPipedInputStreamgetIn(){returnin;}publicvoidrun(){byte[]buf=newbyte[1024];try{intlen=in.read(buf);System.out.println("thefollowingisfromsender:\n“+newString(buf,0,len));in.close();}catch(Exceptione){e.printStackTrace();}}}程序的执行结果:
thefollowingisfromsender:Hello,receiver!I`msender组件对数据的处理的过滤器sender和receiver。连接件关键语句(1)PipedOutputStreamout=s.getOut();这条语句作用是发送端送出数据。(2)PipedInputStreamin=r.getIn();这条语句作用是接收端接收数据。(3)in.connect(out);这条语句作用是衔接管道两端。3.3基于事件的隐式调用风格显式调用vs.隐式调用显式调用各个组件之间的互动是由显性调用函数或程序完成的。调用过程与次序是固定的、预先设定的。隐式调用在很多情况下,软件更多的变成被动性系统,组件持续的与其所处的环境打交道,但并不知道确切的交互次序3.3.1基于事件的隐式调用隐式调用:组件不直接调用一个过程一个组件(事件源)可以触发或广播一个或多个事件。系统中的其它组件(事件处理器)可以注册自己感兴趣的事件,并将自己的某个过程与相应的事件进行关联。当一个事件被发布,系统(事件管理器)自动调用在该事件中注册的所有过程。这样,一个事件的触发就导致了另一模块中的过程的调用。这种系统,称为基于事件的系统(Event-basedsystem),采用隐式调用(Implicitinvocation)的方式。基本组件:对象或过程,并分类为以下更小的组件
过程或函数,充当事件源或事件处理器的角色事件连接件:事件-过程绑定过程(事件处理器,事件的接收和处理方)向特定的事件进行注册;组件(事件源)发布事件;当某些事件被发布(触发)时,向其注册的过程被隐式调用;调用的次序是不确定的;基于事件的隐式调用特点优点为软件复用提供了强大的支持,功能扩展比较容易当需要将一个组件加入现存系统中时,只需将它注册到系统的事件中数据通过接口访问,数据格式的变化不会影响其他部分各模块之间的调用隐式化,从而复用性提高为系统动态演化带来了方便组件独立存在,当用一个组件代替另一个组件时,不会影响到其它组件的接口健壮性一个组件出错将不会影响其他组件支持实现交互式系统(用户输入/网络通讯)异步执行,不必同步等待执行结果对事件的并发处理将提高系统性能;缺点分布式控制方式使系统的同步、验证和调试变得异常困难:组件放弃了对系统计算的控制,难以控制各模块之间的处理次序。一个组件触发一个事件时,不能确定其它组件是否会响应它。而且即使它知道事件注册了哪些组件的构成,它也不能保证这些过程被调用的顺序。既然过程的语义必须依赖于被触发事件的上下文约束,关于正确性的推理则难以保证。传统的基于先验和后验条件的验证变得不可能。数据交换的问题:数据可通过事件直接在系统间传递(无调度模块时)。但在具有独立调度模块的事件系统中,数据则需要经过调度模块的传递(基于事件的系统必须依靠一个共享的仓库进行交互)。在这些情况下,全局性能和资源管理成为了系统的瓶颈。使用更多的存储空间基于事件的隐式调用风格应用领域基于事件的隐式调用风格常常被用于如下领域:(1)在程序设计环境中用于集成各种工具。(2)在数据库管理系统中用于检查数据库的一致性约束条件。(3)在用户界面中分离数据和表示。(4)在编辑器中支持语法检查。例如在某系统中,编辑器和变量监视器可以登记相应Debugger的断点事件。当Debugger在断点处停下时,它声明该事件,由系统自动调用处理程序,如编辑程序可以显示到断点,变量监视器刷新变量数值。而Debugger本身只声明事件,并不关心哪些过程会启动,也不关心这些过程做什么处理。3.3.2JAVA的事件处理处理事件的一般步骤是注册监听器以监听事件源产生的事件(如通过ActionListener来响应用户点击按钮);定义处理事件的方法(如在ActionListener中的actionPerformed中定义相应方法)。importjava.awt.*;importjava.awt.event.*; //引入java.awt.event包处理事件classBtnLabelActionextendsFrameimplementsActionListener{//声明窗口类(BtnLabelAction)并实现动作事件接口(ActionListener)
Labelprompt;Buttonbtn;voidCreateWindow(){setTitle("MyButton");prompt=newLabel("你好");//创建标签对象
btn=newButton("操作"); //创建按钮对象
setLayout(newFlowLayout());//布局设计,用于安排按钮、标签的位置
add(prompt); //将标签放入容器
add(btn); //将按钮放入容器
btn.addActionListener(this); //将监听器(窗体对象本身)注册给按钮对象
setSize(300,100);setVisible(true);}
publicvoidactionPerformed(ActionEvente){//接口ActionListener的事件处理方法if(e.getSource()==btn)//判断动作事件是否是由按钮btn引发的
if(prompt.getText()=="你好")prompt.setText("再见");elseprompt.setText("你好");}}publicclassex604{publicstaticvoidmain(Stringargs[]){BtnLabelActionbla=newBtnLabelAction();事件源
bla.CreateWindow();}}事件源注册:btn.addActionListener(监听器对象);监听器动作事件处理方法:publicvoidactionPerformed(ActionEvente)动作事件(ActionEvent)先注册监听器触发事件调用并传递参数e组件注册方法addActionListener()处理事件的方法actionPerformed()发生的事件ActionEvente事件源btn监听器this(窗体对象本身,实现了Actionlistener接口的类的对象)。连接件(1)btn.addActionListener(this):将事件源按钮对象注册到监听器(this,窗体对象本身implementsActionlistener)。(2)系统定义对事件的处理方法,发生的事件为参数:publicvoidactionPerformed(ActionEvente)。(3)点击btn,触发ActionEvent事件,事件管理器(实现了Actionlistener接口的类,本程序为窗体对象本身this)会根据发生的ActionEvent事件,自动调用actionPerformed()方法,执行方法体中的语句。3.4层次风格3.4.1层次风格概念层次系统在层次系统中,系统被组织成若干个层次,每个层次由一系列组件组成下层组件向上层组件提供服务上层组件被看作是下层组件的客户核心层-功能层-应用层层次软件体系风格基本组件:各层次内部包含的组件连接件:层间的交互协议拓扑结构:分层拓扑约束:对相邻层间交互的约束集中式部署(Mainframe)分布式部署(Distributed)优点支持基于抽象程度递增的系统设计,有利于设计者对一个复杂系统进行分解;局部依赖性,因为每一层至多和相邻的上下层交互,因此功能的改变通常影响相邻的上下层;可复用性,如果某独立层保证了功能的完整性并且提供了文档化的接口,便可在多个语境中复用。可替换性,只要提供的服务接口定义不变,同一层的不同实现可以交换使用。这样,就可以定义一组标准的接口,而允许各种不同的实现方法。对标准化的支持。清晰定义并且广泛接受的抽象层次能够促进实现标准化的任务和接口开发,同样接口的不同实现能够互换使用。可测试性。具有定义明确的层接口以及交换层接口的各个实现的能力提高了可测试性。缺点并不是每个系统都可以很容易地划分为分层的模式,甚至即使一个系统的逻辑结构是层次化的,出于对系统性能的考虑,系统设计师不得不把一些低级或高级的功能综合起来;效率的降低:由分层风格构成的系统,运行效率往往低于整体结构。在上层中的服务如果有很多依赖于最底层,则相关的数据必须通过一些中间层的若干次转化,才能传到;很难找到合适的、正确的层次抽象方法:层数太少,分层不能完全发挥这种风格的可复用性、可更改性和可移植性上的潜力。层数过多,则引入不必要的复杂性和层间隔离冗余以及层间传输开销。目前,没有可行的广为人们所认可的层粒度的确定和层任务的分配方法。3.4.2实例ISO/OSI网络的分层模型传输介质接口通信控制项(通信子网)应用层物理传输介质应用层表示层表示层会话层会话层传输层传输层网络层网络层数据链路层数据链路层物理层物理层应用控制项(资源子网)软件自动测试系统该测试软件被设计成三层第一层为图形用户界面(GUILayer),用于用户选择测试案例、用户输入以及显示测试结果;第二层为测试案例层(TestcaseLayer),软件测试工程师所编写的测试案例都部署在该层;第三层为被测试软件层(ProgramUnerTestLayer),包含所有被测试软件。
在本设计中,用户图形界面层调用测试案例层,选择执行某个测试案例;测试案例层调用被测试软件,调用某个或者几个被测试程序。组件第一层里的TestingGUI类第二层里的Testcase接口、TestcaseBubble类、TestcaseHeap类、TestcaseInscrtion类、ResultVerification类第三层里的BubbleSort类、HeapSort类、InscrtSort类、SortAlgorithm接口。连接件(1)在第一层TestingGUI类中声明了第二层TestcaseBubble类的对象、TestcaseHeap类的对象和TestcaseInsertion类的对象,并调用它们的execute()方法,第二层的各类的execute()方法将一个数组结果返回给第一层。(2)在第二层的TestcaseBubble类中声明了第三层的BubbleSort类的对象,并调用该类中的sort方法;第三层的BubbleSort类的sort方法将对数组的排序结果返回给第二层。TestcaseHeap类和TestcaseInsertion类类似。3.5仓库风格
在仓库风格中,有两种不同的组件:一个是中央数据结构,它说明当前状态。另一个是独立组件的集合,它对中央数据结构进行操作。根据系统中数据和状态的控制方法的不同,可以分为两种类型。一种类型是传统的数据库体系结构,它是由输入事务选择进行何种处理,并把执行结果作为当前状态存储到中央数据结构中。另一种类型是黑板(blackboard)体系结构,它是由中央数据结构的当前状态决定进行何种处理。内存计算知识源黑板(共享数据)知识源知识源知识源直接存取黑板体系结构是仓库体系结构的特殊化。它反映的是一种信息共享的系统——如同教室里的黑板一样,有多个人读也有多个人写。内存计算知识源黑板(共享数据)知识源知识源知识源直接存取黑板系统通常由三部分组成:(1)知识源(knowledgesources,KSs)。软件专家模块,每个知识源提供应用程序所需要的具体的专家知识。知识源之间不直接进行通讯,只通过黑板来完成它们之间的交互。(2)黑板数据结构(blackboard)。一个共享知识库,包含了问题、部分解决方案、建议和已经贡献的信息。按照与应用程序相关的层次来组织的解决问题的数据。黑板可以被认为是一个动态的“库”,知识源通过不断地改变黑板数据来解决问题。(3)控制机制(controlshell)。知识源需要控制机制来保证以一种最有效和连贯的方式来工作,正如人类专家得有一个主持人来防止他们乱抢粉笔。控制完全由黑板的状态驱动,黑板状态的改变决定使用的特定知识。黑板系统的传统应用是信号处理领
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 克罗恩病的护理诊断
- 试验室安全教育培训
- 寒号鸟课件2教学课件
- 3-2-2 物质的量在化学方程式计算中的应用 课件 高一上学期化学人教版(2019)必修第一册
- 脑转移瘤目前治疗策略
- 糖尿病前期指导
- 年终合同管理总结
- 保护我的耳朵教案及反思小班
- 荷花淀说课稿
- 汉教学说课稿
- 《金融科技概论(第二版)》高职全套教学课件
- 风力发电项目施工方案
- (2024年)传染病培训课件
- 沙盘游戏大纲
- 物理化学实验B智慧树知到课后章节答案2023年下北京科技大学
- 实验室安全准入教育(通识A课程)学习通超星课后章节答案期末考试题库2023年
- 无机及分析化学考试题(附答案)
- [精华]^门罗第2本书中文《魂魄出体》FarJourneys
- 木霉菌生防综述
- 劳动合同厦门市人力资源和社会保障局制
- 【教案】《认识计算机硬件设备及作用》教学设计
评论
0/150
提交评论