软件系统概念结构的立体分析法_第1页
软件系统概念结构的立体分析法_第2页
软件系统概念结构的立体分析法_第3页
软件系统概念结构的立体分析法_第4页
软件系统概念结构的立体分析法_第5页
已阅读5页,还剩28页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

因此,对于一个软件系统,我们应该有着一种立体景象。自然的,我们也应该从立体的

视角,顺着垂直与水平两个构造纬度,构造或者分析软件系统。构造或者分析从认识的角度

在内容上并无根本区别,只不过二者获取内容的过程是相反的。

2.1分类和层次

在认识,分析,设计软件系统的过程中,我们的头脑里会出现一系列的概念,比如模块,

类,函数,变量等等。这些概念以及相互之间的关系需要得到反思。

分类是对软件概念的最基本的反思。分类的过程是将若干软件概念归为一些集合的过

程。因为观察角度的不同,同一个概念可能被划分到不同的集合中。但是相互正交的分类却

是值得我们要追求的一种状态。因为那样意味着清晰和简明,虽然这往往是做不到的。

分类的最重要结果是形成了原有概念的集合,这个集合本身将作为一个新的概念出现在

我们的概念结构中。事实上这种将现有概念进行分类,并得到若干作为新概念的集合的过程

就是抽象过程。抽象是软件工程中最重要的设计活动之一。

分类和抽象在概念之间建立了一种层次结构。这是一种多对一的,有序的垂直结构。我

们将集合标签称为上层,而分类里的元素称作下层。如下图所示

的集合,而各自的集合标签就是一种最自然的区分。但是这种区分往往不能让我们对系统结

构里的理解更加深入,比如一个函数使用了一个全局变量,而函数与变量通常是属于不同的

类,而如果我们将这个变量和这个函数划分在某一个集合时就可能让我们对结构有着更好的

理解。这里就使我们有下面分伙和交织的阐述。

2.2分伙和交织

分类的依据是因为在若干个元素之间存在的共同的操作,性质等因素,而分伙是因为在

这些元素之间存在这功能上的关联,也就是性质,状态等因素的互动。也就是说如果一个元

素的某个性质或者状态的变动会导致另外一个元素的性质或者状态的变动,那么我们就往往

将他们分成一伙。

当然分伙的依据总是有些混杂的,因为一个元素可能同若干个元素存在互动,而一些元

素又通过若干个元素达成间接互动,这些现象在软件系统中都是普遍存在的。但是分伙跟分

类存在同样的效果,也就是形成一个集合。

但是这个集合标签与元素之间的关系通常是被忽略的,至少是不像如分类那样形成一种

明显的垂直关系。分伙的效果主要是突出了在集合的元素之间互动以及不同或伙之间的互

动。这使我们对系统的认识得到了简化,归结,因为这时对系统的研究将主要是对不同伙之

间互动的研究,而伙的数量显然常常比原有系统中个体的数量少了许多。分伙体现的是系

统状态变化上不同个体间的交织,这是一个平面的解析。如下图

2.3概念结点

我们在系统的观点下来研究软件系统的结构,也就是将系统看作各种结点的网络,并且

我选择成熟的图理论作为深入研究的工具。

图中最基本的•个方面就是结点,就我们而言就是概念结构。前面我们已经对概念结构

有了初步的认识,在这一节我们将软件系统中概念结构的具体形式进行分析,这里的顺序是

从大概念到小概念。

概念结点在水平分析下是被看作其它概念结点通过合作构造动力交织起来的。同时抽象

构造动力又将概念结点形成了一种有顺序的层次。综合这两种分析,我们将概念结点区分为

6层,每层都是更下层实体的交织。

2.3.1自治系统

自治系统是能够独立的完整某项功能,自主掌握硬件资源的集成的,是被解析出的系统部

分的最粗粒度。

比如一台电脑主机。

2.3.2可执行程序和服务

是操作系统内一道被调度来使用系统资源为完成某个任务的运行的实体。这包括二进制

形式与文本形式。

2.3.3组件和模块

是可被用来作为一个部件被加入到其它程序中,能够完成某个专业功能的实体。比如一

个web服务或者封装了一个相关函数(或者数据)集合的模块。这包括二进制形式与文本

形式。

2.3.4算法和函数

是提供输入输出介面的一个实现。这包括二进制形式与文本形式。如c语言中的函数。

2.3.5基块

是指具有唯一出口与入口的顺序执行的指令序列。这包括二进制形式与文本形式。例如

下面给出了一种用中间代码形式表示的两个基块序列。

a=f(2);

D.1708=2;

goto<D.1709>;

<D.1709>:

returnD.1708;

2.3.6指令和数据

是指机器的一条指令或者机器所能识别的一个原始数据,比如一个寄存器所表示的整数

或者标准的浮点数据。这包括二进制形式与文本形式。

这是在软件系统中所能水平解析的最底层概念结点。

2.3.7总结

在立体的分析法下,概念结点被解析出垂直构造中的6个层次。这6个层次是其它分析

的工场,也就是其它分析活动所在的场所。通常我们关注于第3、4层。因为第5、6层中概

念结点数目将非常庞大,而其中的相互交织关联却是直接简单的。

[软件世界、

自治系统

程序和服务

OOO

组件和模块

O

算法和函数

ooo

基块

指令和数据

ooo

24交织关联

正如一般图中类似,边是用来表示结点之间关系的。一般的边是用来表示同级结点之间

的关系。相应于前面6个层面的概念结点,每个层面内的概念结点的关联都存在着特有的关

联内涵,而且我们认为不同层面之间不存在交织关联。这与我们认为交织关联是一种水平性

质相符。

2.4.1网络互联

这是在自治系统工场层交织关联。在这一层不同的自治系统通过著名的通信协议来实现

相互的合作和共享。比如在互联网中,各个主机使用TCP/IP协议互联的进行互联。这种关

联对各个系统的影响一般不具有强制性,所以每个自治系统都能在一定程度上保证自己的独

立。

2.4.2进程和线程通信

这是在程序和服务工场层的交织关联。这种关联可以通过多种方式来实现,这其实基本

上也是进程通信的内容。多数系统支持文件,信号,消息队列,管道,消息来实现进程通信。

2.4.3模块介面

这是在模块和组件工场层的交织关联。模块之间通过模块介面实现通信,这里经常需要

区分两种介面。一种是使用介面,也就是具有这个模块介面的模块需要另外一个模块来发挥

功能,这时这个模块就这个介面进行规定。另一种是提供介面,也就是一个模块可以向系统

中其它模块提供服务,这时此模块在此模块介面中对自己所能提供的服务进行规定。

2.4.4过程和函数调用

这是在算法和函数工场层的交织关联。算法本身具有输入输出的天然连接,但在实际的

软件系统中算法,或者说函数,之间的关联也就是调用存在多种具体形式。比较著名的有传

值调用,引用调用,地址调用,抄写-恢复调用。

2.4.5控制流

这是在基块工场层的交织关联。基块是顺序计算的基本单位,一个算法的基块通过控制

流的相互连接实现计算衔接。

控制流的关联有两种形式,一种是有条件跳跃,另一种是无条件跳跃。

2.4.6数据依赖

这是在指令和数据工场层的交织关联。软件系统的计算中,一条指令往往引用了另外一

条指令的数据或者其它信息而导致在这两条指令之间存在一种有序的关系,这种关系一般称

之为依赖。

这种依赖关联可以分为数据依赖和控制依赖。数据依赖又分为真依赖,反依赖,和输出

依赖。

2.5图形表示

软件结构图是对软件系统的抽象,抽象的工具与表达形式就前面述及的图。软件结构图

是用来表达软件系统的,自然这里的图的内涵也就是结点与边有着自己的内容。

难点

O

2.5.1结点

用立方体表示概念结点。有时使用菱台形表示结点是整个系统变化的源动力或者肇始。

用菱形来表示媒介结点.虽然媒介本质是关联的,但我们总是将媒介本身作为一种实体

存在来表示。这也是我们的图形表示中的一个特点。

2.5.2关联

用箭头表示一种关联。关联的基本涵义是信息的流动。

2.5.3从属系统

用一个虚线边界的圆形表示被考虑系统中的从属系统,通常是同质结点的汇集。

2.5.4业务

线

使用一条红色的粗线表示一个具体业务的信息流动。这是对系统的动态特征的一种表

达。动态表达总是成为系统的图形表示中的难题。

2.6典型拓扑构形

概念结构的图形表示有几种常见拓扑构形,这些构形中往往成为应用中存在的主要构

形。因为这些构形有着非常强大的表现能力。

2.6.1线状

所有的被考虑概念结点形成一种单线状构形,也就是每个概念结点至多有两个关联概念

结点。这种构形简单,容易实现和管理。因此总是成为系统构造和理解的首要选择。

2.6.2树状

所有被考虑的概念结点之间或者存在一种直接的有序的归结关系,或者是通过间接归结

形成关联,并且存在一个称之为根的概念结点。

2.6.3网状

所有被考虑的概念结点存在间一种复杂的错综关联。通常这为人们所避免,而尽可量用

规则的网状,如星形,立方体等构形来满足应用。

3设计模式

3.1概述

设计模式是发生在软件设计中通常发生的问题的可复用的解决方案。设计模式不是能够被直

接变成代码的完成了的设计。它是关于一个能够用在许多不同情况下的如果解决问题的描述

或者模板。设计模式起源于一种建筑学上的概念ChristopherAlexander(1977/79),在1987

年,KentBeck与WardCunningham开始试验将模式应用到编程中的想法并将他们的结果提

交在拿年的OOPSLA会议上。在随后几年,Beck,Cunningham跟其它人在这个工作上跟随。

设计模式在计算机科学中获得流行是在一本名为DesignPatterns:Elementsof

ReusableObject-OrientedSoftware的书在1994年被叫做"GangofFour"(Gamma等人)

的作者出版之后。那同一年,第一次PatternLanguagesofProgramming会议召开,而后

一年PortlandPatternRepository被建立为设计模式的档案但术语的范围任何是件有争议

的事情。

物体-导向的设计模式典型的说明在类之间或者物体之间的关系和介面,而不规定涉及

的最终应用类或者物体。许多模式隐含物体导向或者更一般的可更改状态,且因此不可应在

函数式编程语言中,在那里数据是不可更改的或者类似对待。

有许多哦类型的设计模式,主要有算法策略模式的论述关注点相关于描述如何开发在一种计

算平台上的应用特征的高级策略。计算上的设计模式的论述关注点是相关于关键计算识别。

执行模式关注相关于支持应用执行,包括咋任务的执行流里面的策略跟建造块来执行任务同

步。实现策略模式的论题关注相关于实现源代码来支持程序组织以及特定于并行编程的通用

数据结构。结构设计模式所论述的东西关注相关与正被开发的应用的高级结构。在范围上比

设计模式更大的是建筑模式,通常描述为整个系统跟随的整体模式。

下面我们将用我们的观点详细分析23中经典设计模式,这23中设计模式被归为三类。

每种模式的分析通过三部分组成:

首先,我们讲述该模式的总体概念,并给出立体分析法的图示;然后,我们在业务线一

节描述系统中动态变化和相互作用;最后,我们对这个系统的特点进行简要评价。

3.2创建类模式

处理对象创建机制的设计模式,尝试以适合实际情况的方式来创建对象。物体创建的基

本形式能够导致设计问题或者添加复杂型到设计中。创建的设计模式通过以某种方式控制这

个物体的创建来解决此问题。创建设计模式进一步被归类成物体创建模式跟类创建模式,旗

子物体创建模式处理物体创建而类创建模式处理列的实例化。

3.2.1抽象工厂模式(AbstractFactoryPattern)

为一个产品族提供统一的建造介面。当需要这个产品族的某一系列的时候,这可以从抽

象工厂中选择相应的系列来创建一个具体的工厂类。

基础结构

抽象工程模式从软件结构分析的角度有5个结点族:

工厂介面

1、用户(1-1)

2、产品介面(2-1)是抽象工厂和用户之间的契约,用户通过此介面从抽象工厂获得

自己需要的产品。

3、抽象工厂(1-2)向用户提供符合产品介面规定的产品,而实质的构造可能来自各

种具体的生产厂家。

4、工厂介面(2-2)

是抽象工厂和生产工厂之间的契约,可保证抽象工厂通过此介面获得符合要求

的产品。

5、生产工厂(2-3)生产最终实体产品,也就是用户需要的产品的源头厂家。它必须有

生产工厂介面所规定的产品并提供给抽象工厂的能力。

业务线

存在一条可用产品的获取过程通路。也就是用户向抽象工厂发出请求,然后抽象工厂向

生产工厂获取,并最终按原路返回,将产品提交给用户。

编码是(<1,1>,<2,1>,<1,2>,<2,2>,<2,3>,<2,2>,<1,2>,<2,1>,<1,1>)。

评述

在软件开发里,工厂是代码中物象被构造的地方。抽象工厂模式将一个物体集合的实现细

节跟彳巨俚的一般用途分类开来•这使得互换具体类而不影响改变彳巨俚的代码即使是在运行时。

这种跟类似的模式,导致初始代码中不必要的复杂型以及额外的工。正确使用“额外”工作

在应用工厂的第二个实例里得到补偿。

3.2.2建造师模式(BuilderPattern)

基础结构

从结构观点看,建造师模式的结构中有如下五个结点:1、

用户〈1,1〉

对物象提出请求。2、

取用介面<2,1>

3、总管<1,2>回应用户的请求,根据用户的请求组织物象创造的各种工序,

实际的工序

被提供给分务承造者。

4、吩咐介面连接统管跟分务承造者,让分务承担者按照统管的要求行动。

5、分务承担者完成总管一个产品提出的每一具体的任务。

业务线

<1,1X2,1>«1,2X2,1X1,3»*<2,1X1,1>

实现一个复杂物象的创造。

评述

建造者模式关注于一步一步的来创建一个复杂的物象,并且将这个复杂的步

骤(工序)专门抽象出来,这就是总归的工作,从而实现用户与复杂性分隔。

3.2.3工厂方法模式(FactoryMethodPattern)

定义一个介面用于创建对象,但是让子类决定初始化那个类。工厂方法将一个类的初

始化下放到子类中。

基础结构

工厂方法在结构观点下有三个结点:

1、用户

提出物象的需求。

2、获取介面连接用户跟工厂,将用户的需求提交个工厂,并将工厂生产出

的产品(物

象)送达用户。

3、工厂

祸据用户的需求生产出物象,而具体的方法和细节对用户来说是被屏蔽

这不结构如下图所示:

业务线

从用户经过获取介面向工厂传递需求信息,并从工厂经过获取介面向用户传递产品。

编码为<1,1x2,1><1,2>|卜

评述

工厂方法将用户和自己的需求的详细描述与实现隔离开来,这些复杂任务被

交给工厂,而用户的知识只需要是获取介面。正如[1]中所说工厂方法模式的本

质是“为创建象而定义一个介面,但让衍生类来判断要实例化哪种类。工厂方法

让类可推延实例事务给衍生类。”

3.2.4.原型模式(PrototypePattern)

从软件结构的观点看来,原型模式讲的是一个结构中结点的所具有的操作方法。这是一

种仿造的操作,象通过仿造来生成一种新象。

基础结构

仿造

象甲

评述仿造信息流通提供了一种直截了当的造象方法,避免了标准方法的成本,也避免了

在客

户应用中需要了解特定的衍生类细节。

3.2.5独象(SingletonPattern)

从结构的观点,就一个系统中结点的数目进行现在,对系统的引入操作不会添加新的结

点。

有契约引入

基础结构

在系统的一个分伙中,限定了象的数目。典型的是一个。这通过一个分伙图示中画出一

个单独的象来表示。

独象

业务线评-

独象模式有时在协调跨系统的行动是有用的,但会在系统中引入全局状态,妨碍系统的

并行。

3.3结构类模式

结构设计模式是通过识别出一种简单的途径来实现实体间关系来松弛设计的一个设计模

式。

3.3.1适配器模式(AdapterPattern)

将某个类的介面装换成领一个介面表示。界面模式可以消除介面不匹配所造成的兼容

性问题。

适配器模式是关于创建一个转换,或者映射,就部件到系统的中介抽象的。从软件结

构的观点,适配器存在5个结点:

1、用户

系统中提出功能需求的部件,触发系统状态变化的源头。

2、新介面

连接用户和配接器,将用户的功能需求传递给配接器。

3、配接器

接受用户的功能需求,进行初步处理,而将任务中实质性的部分通过旧介面传递给功能

提供者。

4,旧界面

连接配接器跟原先功能提供者,使得原有系统部件能够按照自己的方式工作。

5、原先功能提供者通过自己固有的方式工作的旧的

功能性部件。评述

适配器充当一个已经存在的类的包装或者修饰者。可以提供给那个类一个不同的或者变

换过的视图。

3.3.2桥连模式(BridgePattern)桥连模式要达到的效果是将一

个抽象与其实现解耦,以使二者可以独立变化。从软件概念结构的观点看来,

桥连模式含有5个基本结点

基础结构

1、用户

触发系统状态变化,采取行动的源头。

2、抽象介面连接用户和需求相应者,将用户的需求直接传递给需求响应者。

3、需求响应者

4、实现介面

5、需求实现者业务

线

<1,1>

评述

桥连模式通过将一个需求介面分解为抽象介面和实现介面,致使这两方面在软件的进化

中可以独立变化,而保证系统得到最大复用。

3.3.3组合模式(CompositePattem)

把多个对象组成树状结构来表示局部与整体,这样用户可以同样的对待个别对象与对象

的组合。

从软件概念结构的观点看来,组合模式分析如下。

基础结构

组合模式的概念结构视图中包含有5个结点,四条边。

2、一致介面一

3、响应整体

4^一致介面二

5、相应个体业务

线

评论

组合模式组合各个象到一个树结构里,从而表示出了部分-整体的层次结构。并且

由于中间的两个间接结点是相同的(都是一致介面),这使得用户可以一致的对待

个体跟组合体。

3.3.4修饰模式(DecoratorPattern)

向某个对象动态的添加更多的功能。修饰模式是除类继承外另外一种扩展功能的方

法。

从软件概念结构的观点出发,我们在下面对修饰模式作出如此解析。

基础结构

业务线评

修饰模式使得在运行时拓展(修饰)一个特定象的功用变得可能,而独立于相同类

的其它实例,在假定设计时已经完成了一些打底工作。用户因此既可以通过原有的简朴

介面跟修饰着交往,也可以使用修饰介面跟修饰者交往,而修饰者充分利用了原本的功

用。

3.3.5外墙模式(FagadePattern)

这个名字的由来是类比与建筑上的外墙。外墙是到一个更大的代码体,比如一个类库,

的简化后介面的物体。

外墙能够:使得一个软件库更加容易使用,理解和测试,因为外墙对于通常的任务有着

方便的方法;基于同样的原因,使得使用此库的代码更加易读;减少外部代码对库的内部工

作机制的依赖,因为多数代码使用此外墙,因此允许在开发此系统中的伸缩性;用一个良好

设计的API包装一个糟糕设计的API集合。

为子系统中的以群介面提供一个统一的介面,外观模式定义了一个高层介面,这个介

面使得这以子系统更加容易使用。

从软件概念结构的观点出发,我们在下面对修饰模式作出如此解析。

框架

业务线

评论

外墙模式为交往巨大的代码集提供了一种简化的介面。可以使得软件库的使用更加

容易使用,理解,和测试,也使得使用此库的代码容易读懂,并减少了库外部代码对这个

库的依赖,也能为设计上糟糕的API集合提供一个单独的有着良好设计的APL

适配器模式用于包装体需要遵守一个特别的介面且必须支持一种多态行为时。另一方

面,外墙用在想要有一个更容易或者更加简单的介面来使用。

3.3.6轻便模式(FlyweightPattern)

轻便体是通过跟其它类似的物象共享尽可能多的数据来最小化内存使用的物象;这是在

一种简单重复的表示将会使用不可接受数量的内存时大量使用物象的一种途径。这个术语来

源于拳击运动中的轻量级。

通过共享以便有效的支持大量细粒度对象。从软件概念结构的观点出发,我们在下面对

修饰模式作出如此解析。

区别是应求者的做事方式或者算法。从软件概念结构的观点出发,我们在下面

对修饰模式作出如此解析。

评论

通常对象状态的某些部分可以共享且将它们放入外部的数据结构并且在他们被使用

时将这些外部数据临时传入这些轻便对象是很普遍的。

在其它场合共享等同数据结构的想法被叫做散列控制台操作(hashconsing)o

3.3.7代理模式(ProxyPattern)

代理,在最一般的形式下,是充当到某种其它东西的介面的类。代理可以介面到任何其

它东西上:一个网络连接,内存中的一个大对象,一个文件,或者其它对于复制是昂贵或者

不可能的资源。

为其它独享提供一个代理来控制对这个对象的交往。

框架

以减少应用的内存印迹。

3.4行为型模式

行为模式是识别在对象之间共同的通信模式跟实现这些模式的设计模式。通过这样做,

这些模式增加了执行这种通信的韧性。

3.4.1责任链模式(ChainofresponsibilityPattern)

为解除请求的发送者与接受者间的耦合,而使多个对象都有机会处理这个请求。将这

些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。

3.4.2命令模式(CommandPattern)

将一个请求封装为一个对象,从而你可用不同的请求对客户进行参数化;对请求排队或

记录请求日志,以及支持可取消的操作。这些信息包括方法名字,拥有此方法的对象跟用

于方法参数的值。

框架

客户实例化命令对象,并提供在后面使唤此方法所要求的信息。

召唤者决定此方法什么时候应该被使唤。

接收者是包含此方法的代码的一个实例。

评论使用命令模式使得构造在选择的时候需要委托,安排顺序或者执行方法的一般部件

而不

需要知道此方法或者方法参数的拥有者的一般部件更加容易。

3.4.3解释器模式(InterpreterPattern)

给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用^表示来

解释^言中的句子。

解释器模式规定如何求值语言里的句子。基本想法是对于在一个特殊的计算语言里的

每个符号(终结符或者非终结符)都有一个类。

框架

3.4.4迭代器模式(IteratorPattern)

提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。

迭代器被用于遍历一个容器并交往容器的元素。迭代其模式将算法从容器解耦了出来。(在

一些情况下,算法必须是容器规定的且因此不能被解耦)。c类语言中指针就是一种迭代器。

3.4.5媒介器模式(MediatorPattern)

通常一个程序由许多(有时很巨大)个类组成。因此逻辑跟计算都被分布在这些类之间。

然而,由于更多类是在程序里开发的,特别是维护跟/或者再构期间,这些类之间的通信问

题可能就变得更加复杂。这使得程序更加难以阅读和维护。进一步,这可能变成变更程序的

困难,因为任何的变动都可能给影响在几个其它类里面的代码。

在媒介器模式下,对象间的通信被用一个媒介器对象来封装。对象不再跟每个其它对象

直接通信,但是代之以通过媒介器来通信。这减少了在通信对象间的依赖,因此降低了偶尔。

框架

3.4.6备忘录模式(MementoPattern)

备忘录模式由两者来使用:发起者跟看管者。发起者是有一种内部状态的某种对象。看

管者打算为发起者做些事情,但想要能够撤销这种状态。看管者首先向发起者请求一个备忘

体。然后做它所要求的任何操作(或者操作序列)。为了回滚到此操作之前的状态,看管者

返回一个备忘体给发起者。备忘体自身是一个不透明物体(看管者不能,也不应该,改变的

东西)。

框架

3.4.7观察者模式(ObserverPattern)

在对象间定义一个对多个的联系,由此当一个对象改变了状态,所有其他相关的对象

会被通知并自动刷新。

在这里,一个被叫做主题的对象,维护着彳巨俚的依赖册子,被叫做观察者,并自动通

知彳巨俚任何状态的变动,通常是通过使唤彳巨俚的方法之一。这主要用于实现分布式的时间处

理系统。

框架

3.4.8状态模式(statepattern)

这个模式用在表示一个对象状态的程序里。这是在运行时部分改变彳巨的类型的一种干净

途径。

框架

3.4.9策略模式(StrategyPattern)

策略模式意图提供一种方法来定义一族算法,封装每个成为一个对象,并使得它们可以

相互改变。策略模式使得算法独立于使用彳巨俚的客户。

编程语言里的本质需求是存储引用在数据结构里某些代码并取出它的能力。框

3.4.10模板方法模式(Templatemethodpattern)

在一个操作中定义算法的骨架,将其中某些步骤托付个子类实现。模板方法让子类定

义算法中的某些步骤而不修改算法的结构。

模板方法定义了一个算法的程序骨架。这些算法步骤的一个或者多个可被子类叠骑,

以此在确保中心算法仍然被服务的情况下允许不同的行为。

框架

算法—抽象数据

评论

模板方法模式强相关到非虚介面(NVI模式。NVI模式认识到召唤从属抽象方法的非抽

象方法的利益。这种间接层次允许相关于抽象操作的预先操作以及后续操作能够立即发生,

并且允许将来不可预见的变动。NVI模式能够用非常少的软件产品跟运行时成本来开发.

3.4.11访问者模式(vistorpattern)

访问者模式是分隔算法跟彳巨所操作的物体结构的途径。这种分隔的实践效果是添加新

的操作到已经存在的物体结构而不修改那些结构的能力。本质上,访问者模式允许添加新的

虚函数到一个类族而不修改那些类彳巨俚自家;替代的,可以创建一个实现所有这个虚函数的

素颜恰当的专门的访问者类。访问者采用这个实例引用作为输入,并通过双重派遣实现这个

目标。

框架

评论

在能力上,访问者模式比传统的虚函数更受限制。为没有在每类里面添加一个小回派方

法的类创建访问者是不可能的。在原生的实现中,每个类的回派方法是不可继承的。双重

派遣是多重派遣的特殊形式,是将一个函数调用依赖与在此调用中被召唤的两个物体的

运行时类型派发到不同的具体函数的机制,在代码中从一个函数里被调用的具体函数依赖于

一个单独物体的动态类型,因此彳巨俚被称作单独派遣调用,或者简单虚函数调用。

3.5并发模式

并发模式是处理多线程编程范式的设计模式。

3.6总结

设计模式研究的是一种比较微观的结构现象。所以这些现象在软件结构领域普遍的存

在。这些现象有两条非常显著的东西。

一是发生关联的结点之间往往通过一种强制性的契约来约束和规范双方的关联。二是

结点之间的关联往往经过第三方媒介,媒介的存在将双方的相互依赖性减弱了,并

且经常出现一种专业的实体性的媒介。

4软件建筑

软件建筑学科集中于通过抽象和关注分隔来减少复杂性。软件建筑的概念首先是

在EdsgerDijkstra于1968年和DavidParnas于1970年代早期的研究工作中认明的。这

些人着重软件系统的结构并认为正确获取结构是关键的。由于在1990年代人们对建筑风格

(模式),建筑描述语言,建筑档案跟形式方法等作了大量研究,软件建筑这一领域就变得

流行起来。

虽然迄今在软件建筑上做了许多的研究和发展,但是对“软件建筑”这一术语的精确定

义上人们仍然没能达成一致。因为在通往建造一个系统的正确道路上并没有清晰规则,设计

软件建筑仍然是艺术和科学的混合。但不管怎样,软件建筑仍然可以指导软件相关人员如何

采取步骤,如何进行任务。

我们将在这一章从软件概念结构的观点出发,运用我们的表示方法来分析几种著名的软

件建筑风格。软件中概念结构里的一些基本原理将再一次发现,也证明了我们的分析方法是

行之有效的。

4.1层次型

层次风格的建筑中最重要的概念是抽象层(或者抽象级)。在软件概念结构的分析中,

这就是结点。抽象层是隐藏特定功能集的实现细节的途径。是一个模型或者算法的概括,远

离任何具体的实现。这些概括来自宽广的类似事物,通过表示出现在各种具体实现里面的类

似特性的模型封装起来。好的的抽象层所提供的简明性使得通过提炼一个有用的概念或者象

征让复用变得容易,这种适用的场景能够被快速识别。多个抽象层通常按照线性结构组合成

一个抽象级别的等级体系。

框架

2、层介面

业务线

评论

层是具有相同的对其它模块的链依赖集的类组。换句话说,层是在类似的环境中能够复用

的组件的群组。编程语言里,这通常表示为软件模块之间的"import"依赖。

4.2管线与过滤器型

管线由一个处理元素(进程,线程,协同程序,等…)链构成,被安排得使得每个元素

的输出是下一个元素的输入。通常有一定量的缓冲被放在连续的元素之间。在管线里流动的

信息经常是记录,字节或者比特流。

框架

业务线评

4.3黑板型

在黑板型建筑中,有一个共用的知识基地一一“黑板”,它会被一个成分多样的专业知

识源迭代更新,从一个问题说明开始,以一个解答结束。每个知识源在其内部约束匹配黑板

的状态时用一个部分解来更新黑。通过这种方式,专家们合作来解决问题。这种建筑最初是

设计为处理复杂,病态定义问题的一种求解方式,在那种情况下解总是它个各个部分之和。

框架

黑板型系统应用有三个主要部件构成:

1.软件专家模块,这也被叫做知识源(KSs).每个知识源提供应用所需要的特殊专业

知识。

2.黑板,这是一个共享的问题、部分解、建议跟贡献出的信息的贮存库。黑板也可被

认为是最近被其它知识源“提出”过的对当前问题的贡献的一个动态库。

3.控制壳,控制系统中问题解决的活动流。为防止软件专家的相互干扰,KSs需要一

种机制最有效和凝聚的形式来组织软件专家的使用,而这由控制客提供。

评论黑板系统中支持在不同知识源之间的交互和协作为设计和维护应用提供了巨

大的弹

性。因为技术发展的步伐在加快,在软件模块过时情况下能够被替换是非常重要的。

4.4基于事件隐匿召唤

在这种建筑里面系统的结构是围绕事件处理的,使用回派的形式。这密切相关域控制反

转的原则。

“暗中召唤后面的想法是取代直接召唤一个过程,一个组件能够宣布(或者广播)一个或者

更多的事件。系统里的其它部件能够通过关联一个过程到这个事件上来在注那个事件里注册

一个意向。当这个事件被公布时系统自家就召唤所有己经为此事件注册过的过程。因此一个

事件宣布暗中会导致在其它模块里过程的召唤。”

框架

4.5以数据为中心的建筑

数据库中心的建筑或者数据为中心的建筑有几种不同的意思,一般是相关那种数据库在

其中扮演了一个至关重要角色的软件建筑。经常这种描述意味着与其它可选方法的一种对

比。例如,“数据库中心”的建造可以是如下几种的组合:

(1)使用一个标准的,一般用途的关系数据库管理系统,相对于定制的记器里或者基于

文件的数据结构跟交往方法。

(2)使用动态的,表驱动的逻辑,相对于在之前编译过的程序里的逻辑。

(3)使用运行在数据库服务器上的存储过程,跟更加依赖与运行在多层建造里的中间

件应用服务器上的逻辑。

(4)使用一个共享的数据库作为在分布式计算应用里的并行进程间的通信基础,相对

于经由消息传递函数跟消息导向的中间件的直接进程间通信。

框架

评论

表驱动的逻辑可以使得程序更简单和更有弹性。数据库为中心的建筑使得软件

更容易开发和维护。在分布式应用中通过利用DBMS提供的事物处理和索引可以达

到高程度的可靠,性能。

4.6面向服务的建筑(SOA)

是计算里面系统开发和集成结点一些设计原则的有弹性集合。基于SOA的系统将功能

打包成能在多个,分隔的来自儿个商业领域的系统里使用的可互操作的套装。

SOA一般也为服务的顾客,比如基于WEB的应用,提供途径来觉察到可用的基于SOA

的服务。而XML通常被用来作为SOA服务之间进行交接,尽管这并不被要求。SOA定义

如果如何广泛的来为WEB环境和使用多个实现平台来集成分割着的应用。不是定义API,

SOA是根据协议和功能来定义介面。

框架

评论

服务导向的建筑要求服务跟操作系统,以及其它潜伏在应用下面的技术有着松散耦合的

关系。SOA将功能分隔成不同的单元,或者服务,而这些东西开发者能够在网络上可与之

交往,从而允许用户在应用的产品中组合或者复用它们。这些服务跟彳巨俚相应的顾客通过按

良好定义的,共享的格式传递数据来通信,或者通过在多个服务之间协调一个活动。

4.7三层模型

三层(Three-tier)模型是用户介面,功能处理逻辑(“业务规则”),计算机数据存

储与数据交往被作为独立模块来开发和维护,最经常存在于分离的平台上,的一种客户-服

务器建筑。是JohnJ.Donovan在OpenEnvironmentCorporation(OEC)开发出来的。客

户-服务器特征描述了应用中程序间的合作关系。服务器部件提供对一个或者多个客户的功

能或者服务,可发起对这样的服务的请求。

框架

1、提交层

显式相关比如浏览商品,购买,跟购物车内容的信息。彳巨通过输出结构到浏览器/

客户层来跟其它层进行通信。

2、业务处理介面连接提交层与应用层,向应用层传递各种命令以及向提交层回送

各种处理结果。

3、应用层

这一结点是从提交层中拔出来的,也被称为业务逻辑,逻辑层,数据交往层或者中

间层。它通过执行细琐的处理来控制应用的功能。

4、数据服务介面连接应用层与数据层,回应应用层的数据查询和存储以及

数据获取请求。

5、数据层

这一结点构成整个系统中的数据服务器。信息在此被存储和获取。这结点还保持数

据中立和独立于应用服务器或者业务逻辑。

业务线

评论

跟有着良好设计的模块化的软件的通常优点不同,三层建筑意图允许三层中的任一个都

可随着需求或者技术变动而被更新或者替换。

4.8总结

相比设计模式,软件建筑关注的结构层次更加粗略和宽广。软件建筑中强调概念结构图

中每个结点的功能完整性,也就是一定程度的独立和提供服务的能力。

这里媒介之类的细节没有如设计模式中那么受重视,取而代之的是分解和积聚成为软件

建筑中的核心关注。

5.结论和展望

前面我们已经对软件概念结构所要研究的对象有了基本的认识,并且通过对设计模式和

软件建筑进行概念结构分析,这一认识得到深入和佐证。

这一章,我们将在更高的抽象层次上总结和论证软件系统中的基本原理,这是对各种软

件系统中的各种结构现象做的概括。最后我们据此分析了软件工程里众所周知的通用的工程

方法。

5.1基本结构原理

结构这一词的意义是部分组成整体,部件造成系统的一种固化后的成果所带来的外部观

感和内在的道理。

结构分析是认识,分析事物的重要方面,籍此我们可以对事物的整体和部分,全体和个

体的方方面面的关系作出详尽解释。结构分析也是我们进行制造,创建的基本工序。任何制

造和创建都可以看作是拆分,裁剪,组合,搭配的过程,而这写过程和步骤都在基于结构分

析所获得认识的指引和约束下进行。

结构在软件工程领域更有着突出的作用.软件工程实践中形成的概念,比如过程,模块,

接口,介面,封装,架构等等概念都直接是结构的内容,因为软件正是许许多多的代码文本,

各种库,多样的运行时环境的精心组合才生成出来的。

我们将在一节对结构中的四大基本原理做一些论述。这四大基本原理是分解,积聚,契

约,媒介。

5.1.1分解

系统总是可以分解的,这是我们对系统的基本预设。当然,分解的进行总是在一定的层

面上进行的。分解的层面是指系统分解出来的单元,部分的类属。

分解单元如果属于己知类属,则是一种很好的分解,因为这样我们能够利用已知的知识

进行进一步的分析,并且这样会比较完整,而不是零散。

分解是为了认识上的方便,也就是说分解使得我们可以深入的理解系统,了解系统所表

现出来的复杂的,甚至是难以捉摸的性质。如果分解不能达成这个效果,那么分解是失败的。

成功的分解应该给出系统运行的一目了然的视图。

分解出来的单元的规模和复杂度是分解的细致量。细致量应该按照需求来决定,过细和

过粗都不会达成方便我们认识系统的目的。

分解本身是一个递归的过程,这是内在规定的。因为我们认为系统是可分解的,并且认

为分解出的单元也系统,那么我们就必然认同这点。当然我们的认识要求总是受到各种方面

的限制,这也就是决定了分解实际上并非是一个无限的递归过程,是有限的,通常只是在一

两步后就终止。分解递归中的迭代次数就是分解的深度。

5.1.2积聚

积聚是分解的反面,分解将一个大系统拆散为多个小系统,而积聚将多个小系统组织成

一个大系统。积聚的进行也受到环境的容量和这些公组织的单元系统的聚合能力决定。

积聚的规模是对参与积聚的单元的数量的衡量。系统的积聚规模应该受到理性自觉的控

制。过小的积聚可能不能实现系统目标,而过大的积聚也因为积聚引发的问题而使得最终的

系统同样不能达成目标。

积聚的进行应该不能让系统的复杂度变得难以控制,这种复杂性常常体现在积聚单元的

关联。这些关联的度量就是系统的耦合度。复杂的积聚不仅难以进行,而且构造出的系统也

更加脆弱,和不可靠。

5.1.3契约

在分析的观点下,可看到部分之间的关联。关联是系统的本质。系统中关联的特征很大

程度上决定了系统的特征。

在工程中系统总有容错,可靠,可移植等目标,这些都要求在系统的关联中体现。在程

序中不同部分的关联,最简单的是通过各种元素数据,常常是变量的直接牵扯。这种关联虽

然总是很直接,方便,但是却将系统变得复杂和难以管理。

工程经验告诉我们系统不同部分之间的关联应该通过相对稳定的,相对正式的接口来表

达。这种接口介面实际上就体现了一种契约关系。

契约是不同部分之间的共识,是相对成熟,经得住考验的合同。当系统的不同部分之间

通过契约来关联时,他们之间的相互依赖和相互耦合程度就降低了。因为他们之间不再需要

深入对方,了解对方的全部细节,而只需要掌握共同的契约所规定的内容。

因此,通过契约来建立系统的部分之间的关联是构造系统的一条重要准则。

5.1.4媒介

媒介是关联在系统里面的进一步突出。相比于契约,媒介更加稳定,而且变动可以动态

变化,而不影响所联结双方的关联。

通过媒介关联的两部分之间的耦合程度被降到最低。如果要实现两部分之间的松散耦

合,那么媒介就是一种很有用的机制。

5.2工程原则和方法

根据对软件系统概念结构的系统分析方法,我们自然的提出软件工程里系统构造的四个

一般步骤,也就是概念抽象,结构分析,部件连接,总体综合。这四个一般步骤的内容在下

面得到相应论述。

5.2.1概念抽象

立体分析法将软件系统的概念构造分为通过抽象形成的垂直构造和通过交织形成的水

平构造,所以很自然的概念抽象是软件系统构造过程一般步骤中的第一个步骤。概念抽象其

实就是从大量的事物中概括共同的东西。

概念抽象步骤有三个基本议题。第一个议题是通过概念抽象来描述需求,并使用概念抽

象来解决需求。这项议题在软件

开发中一般有语言本身内在规定。比如在C++中,描述复杂的数据对象必须使用类等抽象。

以抽象概念为原型,构造实例的,运行的对象是使得软件开发走向通用的基本途径。

第二个议题是通过抽象来复用代码,避免系统中的重复以及因重复带来的种种问题。这

也是所谓的“抽象原则”所表达的主要内容。抽象原则是减少程序中信息重复(通常意味着

着重代码重复)的基本格言。人们一般是利用编程语言或者软件库所提供的抽象来达到的。

这个原则有时会被表达为对程序员的一个建议,但是有时也被表达为编程语言的要求,假定

为什么要求使用抽象的原因是自理解的。但对于程序员而言,抽象原则可以概括为“不要重

复你自己”原则,这项建议一般避免了信息的重复,也避免了软件开发过程中人力的重复。

程序中每个有意义的功能片应该只被实现一次。在类似的函数被不同的代码片来执行的地

方,通过从各个部分抽象出将它们组合成一个通常是有益的。

第三个议题是概念抽象应该关注开发/封闭原则所关注的内容。在物体-导向的编程中,

开发/封闭原则认为“软件实体(类,模块,函数等等)应该对于扩展开发,但是对于修改要封闭”;

也就是实体能够允许它的行为被修改而不用改动它的源代码。这项原则在产品环境中尤其

有价值,因为对源代码的改动可能必需代码复审,单元测试,以及其它类似的过程来验证

它可用在产品中,而遵循了这种原则的代码在它被扩展时就不需要改变,且因而不需要这

样的一些努力。

开放/封闭原则存在两种解读途径,一种Meyer的开放/封闭原则,另一种是多态式开放

/封闭原则。这两种解读途径都使用继承来解析外在的困难,但是其中所包含的目标,技术,

和结果是却不同的。

Meyer的开放/封闭原则的想法是某个类一旦完工,它的实现就只能被修改来纠正错误,

新的或者改变后的特征都要求创建一个不同的类。而这个不同的类通过继承来复用原来类的

代码。派生的子类可以有也可以没有跟原来类相同的介面。Meyer的定义提倡的是实现方式

的继承。实现方式的能够通过继承来复用,而介面规定彳巨不需要是。已经存在的实现方式对

于修改是封闭的,而新的实现方式不需要己经存在的介面。

1990年代开发/封闭原则被重新定义为抽象介面的使用,实现能够被改变而多种实现能

够被创建且可多态的为其它的所替换,这就是多态式开放/封闭原则。与Meyer的解读途径

相对比,这种定义提倡的是对抽象基类的继承。介面规定能够通过继承来复用但是实现不需

要。已经存在的介面对修改是封闭的而新的实现必须,至少是,实现那个要修改的介面。

5.2.2结构分解

软件系统构造中第二个一般步骤是结构分解,也就是将根据系统的功能特点或者其它考

虑,将系统分成若干个有着更小复杂度的结构的小系统的方法。在我们的立体分析方法中这

相应与在交织构造中获取结构图的结点。

这一步骤有两个基本议题。一个基本议题是关注点的分离

(SoC)»

关注点分离就是将系统分隔成在功能上尽可能少重叠的有着不同特征的部分。关注是程

序中意向或者聚焦的任何一个片块。典型的,关注是特征或者行为的同义词。在通往关注点

分离的过程中,传统上是以编程的模块化跟封装(或者操作的透明)以及在信息因此的帮助

下来达成目标的。分层的设计经常也是基于关注点的分离(例如提交层、业务逻辑层、和数

据交往层、数据库层)。

事实上,关注点分离在许多其它领域同样是一条重要的设计原则,比如城市规划、建筑

和信息设计。目标是将系统设计得功能能够最优的独立于其它功能,因此一个功能的失败不

会导致其它功能也失败,并且一般使得系统更加容易理解,设计和关联复杂的相互依赖的系

统。

方面导向的软件开发(AOSD)是这一议题的解决问题的特殊方法。它寻求系统的新的

模块化以从主程序的事务逻辑中孤立出辅助的或者支持性的功能。AOSD还允许多个关注

点被分开来表达并自动将它们统一成工作系统。典型的,一个方面(aspect)是一系列啰嗦

或者纠结代码,这使得它难以理解和维护。

第二个基本议题是模块的内聚。结构分解出的结点,包括模块之类,存在质量上的要求,

这种质量要求中内聚是最重要

的指标之一。内聚是指软件模块的源代码所表达的功能之间关联的强度。它是一个有序的测

量数量,在谈论中通常表达为高内聚、低内聚等。人们更喜爱有着高内聚的模块,因为这样

的模块通常跟一些软件系统所要追求的特征,包括健壮、可信赖、可复用和可理解,联系在

一起,而低内聚往往跟不软件系统不想要的特征比如难维护、难测试、难复用、和相当难理

解等特征联系在一起。

人们将内聚的类型或者说级别,按从最坏到最好的,做了如下划分:

1、巧合内聚(最坏)模块的各个部分被随意成组,部分之间唯一的关系就是他们被分

在了一起(例如一个“工具”类)。

2、逻辑内聚模块的各个部分被成组是因为他们在逻辑上被分类为相同的东西,即使

根据特征来说是它们不同的(例如所有的鼠标跟键盘输入处理工段成组)。

3、临时内聚模块的各个部分在被处理的时侯成组一一在程序执行的特定时刻被处理

(例如一个在捕捉到错误例外后被使唤的打开文件,创建一个错误记载并通知用

户的函数)。

4、过程内聚一个模块的各个部分被分组是因为跟随着执行的一个特定序列(例如一

个检查文件许可并然后打开此文件的函数)。

5、通信内聚模块的各个部分被群集是因为他们操作相同的数据(例如一个操作相同

信息记录的模块)。

6、顺序内聚模块的各个部分被群集是因为来自一个部分的输出像一个组装线一样输

入到另外一部分(例如一个从文件读取数据并处理该数据的函数)。功能内聚(最

好)

7、功能内聚是模块的各个部分被一组是因为都贡献给模块的单独的良好定义了的任

务(例如义元化一个XML的字串)。

内聚级别名称内聚级别

巧合内聚1

逻辑内聚2

临时内聚3

过程内聚4

通信内聚5

顺序内聚6

功能内聚7

尽管功能内聚是系统结点所要追求的最高级别,但可能是不可达到的。在这种情况下,

通信内聚往往是我们所能够达到的最好级别。

5.2.3部件连接

软件系统构造中第三个一般步骤是部件连接,也就是使用一定的手段和工具将已经具有

连接能力的部件连接起来,使得连接后的部件在总体上初步成为一个能够完成需求所规定的

功能的完整系统。

部件在接连后与连接前存在本质的区别。相互连接的部件之间存在一种特殊的信息交

换,虽然形式上可能有多变,并且这种连接的方式对系统作为整体运行的可靠,效率等各方

面有着根本的影响。所以部件连接是个需要审慎关注的主题。

耦合或者依赖就是一个用来研究部件连接的概念,它指每个模块依赖于其它模块的程

度。耦合通常与内聚形成对比。低耦合经常与高内聚关联,且反之亦然。低耦合是具有良好

结构化计算机系统和良好设计一个迹象,当与具有高内聚的组合时,则大大的有利于达成高

可读性和可维护性的目标。

耦合是有大小的量,人们将耦合根据不同形式按找从大到小的顺序做了如下划分:

1、内容耦合(高)一个模块会修改或者依赖于另外一个模块的内部工作机制(交往

另外一个模块的本地数据),因此改变第二个模块的数据(位置,类型,时序)

就会导致要改变依赖模块。

2、普通耦合两个模块共享相同的全域数据(例如一个全域变数),因此改变共享资源

就会暗含改变所有使用这个共享资源的模块。

3、外露耦合两个模块共享一个外部施加的数据格式、通信协议、或者设计介面。

4、控制耦合一个模块通过传递给另外一个模块它要做什么事情的信息,例如传递一

个做什么的旗子,来控制另外一个模块的流。

5、数据结构耦合模块共享一个组合的数据结构并只使用它的一个部分,可能是一不

相同的部分(例如传递一个记录给一个函数并只使用它的一个域)。这就可能导致

要改变一个模块读取一个记录,只是因为这个模块不需要的域已经被修改过。

6、数据耦合模块通过数据来进行耦合,例如参数。每个数据是一个基本片块,并且

这些是唯一的被共享数据(例如,传递一个整数给计算平方根的函数)。

7、消息耦合(低)这是最松弛的耦合类型,可以通过状态分散(如在物体里面)来达

至IJ,而通信通过参数或者消息传递来完成。

8、无耦合两个模块之间不存在耦合。

耦合级别名称耦合级别

无耦合0

消息耦合1

数据耦合2

数据结构耦合3

控制耦合4

外露耦合5

普通耦合6

内容耦合7

虽然耦合似乎是评价系统的一个反比例的量,也就是耦合量值越大,则系统越差。但是

事情总是存在另外一面,系统的低耦合在现实中的实现过程往往意味着更高的计算负荷以及

更低的性能。因为低耦合往往意味这存在以下几方面的额外计算:

(1)消息创建;

(2)消息传递;

(3)消息翻译;

(4)消息解释。所以部件连接这一步骤的核心议题是耦合,但耦合需要折衷考虑。

5.2.4总体综合

经过概念抽象,结构分解,部件连接这三个一般步骤,系统的构造在概念上就己经初具

雏形,这时我们应该再进行一个总体综合的步骤来完善和调节系统的构造,使得系统能够在

一种最佳的整体配置参数下运行。

在这一阶段,我们可以参照i般职责指派软件原则来检查已经完成的系统构造。--般

职责指派原则,缩写为GRASP,由在物体-导向的设计中指定职责到类跟对象的

诸多要领构成。GRASP中的这些要领包括:信息专家,创建者,控制者,低耦合,高内聚,

多态,纯编造,间接,有保护变动。事实上所有这些要领都回答了一些软件问题,并且几乎

在每种情况下这些问题在几乎每个软件开发项目中都是共有的。这些技术并非被发明来创建

新的工作方法,而只是对物体导向设计中老旧的,尝试并测试过的编程原则进行更好的归档

与标准化。

5.3总结

我们在这篇论文里从各个层面,各个领域对软件系统的构成做了许多分析,提出了我们

对软件系统的认识上的基本观点。然后用此观点重点考察了模式设计与软件建筑的中的一些

著名实例,从此见证了软件系统对结构的基本要求和基本方法。

在第二章,我们了解到了我们所要研究的领域中的基本对象和他们的一般性质,接下来

在第三

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论