体系结构资料:复习提纲

上传人:努力****83 文档编号:162529570 上传时间:2022-10-18 格式:DOC 页数:23 大小:1.11MB
返回 下载 相关 举报
体系结构资料:复习提纲_第1页
第1页 / 共23页
体系结构资料:复习提纲_第2页
第2页 / 共23页
体系结构资料:复习提纲_第3页
第3页 / 共23页
点击查看更多>>
资源描述
1. 名词解释:模块化、信息隐藏、软件体系结构(三个不同方面)、4+1 View、GRASP模式(或其中之一)、设计模式、MVCl 模块化:将程序分成小部分的工作集,即模块,这些模块可以一起组成完整的系统,是抽象和分解的过程。模块被独立对待;可独立理解、使用或重用、构建每个模块;一个模块失败不会影响到其他模块,更易隔离失效;一个模块改变不影响其他模块,限制了连锁反应。模块化要达到模块独立设计、测试、改变、容易集成,从而减少整个软件的成本。对程序的分解会增加复杂性,故产生了耦合和内聚的方法。l 信息隐藏:每个模块隐藏一个重要设计决策的实现即为这个模块的Secret,只有那个模块的组成部分知道细节;模块的接口被抽象精确的定义;可能改变的实现细节被抽象化,不能隐藏的可能改变的部分被参数化;通过被赋予其自己的类、子过程或设计单元,设计的secret被分开,从而达到一个secret变化其他不受影响的目的l 软件体系结构(三个不同方面):从高层结构、关注点和设计决策3个不同方面来理解体系结构;从高层结构方面理解,软件体系结构是部件、连接件和配置组成的,其中部件和连接件是核心的元素,而配置描述这两者的适配情况,这一方面强调了其作为高层抽象的作用;从关注点方面来理解,软件体系结构包括需求(质量属性)、项目环境和商业目标,这一方面体现了不同涉众对于软件体系结构的要求,强调了其作为交流媒介的作用;从设计决策方面来理解,软件体系结构需说明问题、候选设计、理由和解决方案,这是体系结构形成的理由,强调了其指导开发的作用。l 4+1 View:IBM提出的一种multi-point的体系结构模型,共有5个viewpoint,关注点在设计上,特别适用于迭代设计过程,由4个View(逻辑、开发、进程和物理)以及1个特殊viewpoint场景来描述体系结构,不同的涉众可选取自己关系的view来理解。逻辑视图为面向对象的分解,由关键的抽象部件连接件以及配置组成,考虑功能需求,针对终端用户;进程视图为进程分解,有多个层次,包含一个进程网络,软件分解为一组可执行的工作单元,考虑非功能需求,针对集成人员;开发视图为子系统分解,是产品线的基础,有模块和子系统图组成,考虑软件模块的组织层次、管理、重用以及工具,层次式风格,针对编程人员和软件管理者;物理视图将软件映射到硬件,包含网络、task以及对象映射为节点时的拓扑结构和通信,考虑与硬件相关的肺功能呢个需求,针对系统工程师;场景将上面的视图元素组织在一起,通过一小组重要的场景来表现各视图的工作,考虑系统一致性和验证,针对其他视图和评估者等所有用户。l MVC:可以说是一种体系结构风格,也可以说是一种设计模式。分为model、view和controller三种组件;model子系统设计为不依赖任何view子系统和controller子系统,其状态的变化会传递给view子系统;model组件负责维护领域知识和通知view变化,view组件负责显示信息并传递用户指示给controller,controller负责更改model状态和选择响应view,连接件是过程调用、消息、事件、直接内存存取;允许一个model上建立多个独立view,view可同步,可“插拔”(易于修改)的view和controller,但增加了复杂性,view获取数据效率不高,与流行UI工具不十分兼容,适用于UI修改容易并且可以运行时修改、UI的修改不应该影响功能部分设计和代码的应用l GRASP模式:是General Responsibility Assignment Software Patterns的缩写,这些模式不是设计模式,而是对象设计的基本原则,关注对象设计最重要的方面分配职责给类,并不强调体系结构的设计;具体的类型参加条目8l 设计模式:对可重复的设计结构进行抽象,由类和/或对象的依赖、结构、交互或转换组成,提取了设计经验的精化;设计模式有4个要素,模式名增加设计师词汇,问题目的、上下文、何时使用,解决方案类似UML的结构、抽象代码,成果(Consequences)结果和折中2. 模块化l 模块间关系:Connection指向定义在别处的某个label或地址的引用,结构化的定义。l 耦合是衡量模块间关系复杂度的度量l Connection数量接口最小化(Minimize Interfaces);Degree衡量耦合两个模块的连接强度。l Connection的Degree衡量:n 引用模块本身(接口)还是其内部(实现);n 被传送和接收的是什么:数据、印记、控制、完全依赖l 模块的Connection:n 与公共环境(General,Scoped):在共有这个连接的模块间建立耦合;封装将会降低耦合抽象和分解,将潜在共享元素分组,限制每一组的访问途径到可能的最小模块子集。u 假设N1+N2=N, M1+M2=Ml 如果M个模块共享N个元素n 潜在连接数N*M,即(N1+N2) *(M1+M2)= N1*M1+N2*M2+ N1*M2+N2*M1l 如果M1个模块共享N1个元素,M2个模块共享N2个元素n 潜在连接数(N1*M1+N2*M2)n 与其他模块:u 连接复杂性取决于陈述或者理解它需要多少信息。显性关系好于隐形的,最好死语法上显性的;越多Syntactic单元耦合度越高,更简单的接口。u 引用模块本身的连接耦合度低于引用别的模块内部元素的连接针对接口编程l 模块化原则:职责分配,与自己相关的设计决策来表示而不知道其他模块,提供实现上的灵活性,不用处理步骤表示,高内聚低耦合(1) 结构化的内聚与耦合类型;l 耦合(由上而下 耦合度升高,越来越不好):n 数据耦合(Data Coupling)刚刚好的数据;n 印记耦合(Stamp Coupling)数据多于必须;n 控制耦合(Control Coupling)除数据外传递控制元素;n 公共耦合(Common Coupling)n 内容耦合(Content Coupling)数据和控制元素混合;通过一个模块修改另一个模块代码,或者目标模块对于进行修改的模块非常依赖u 数据耦合明显优于印记耦合,数据耦合也优于控制耦合,但印记耦合和控制耦合需要视情况而定;l 内聚n 得到独立模块的方法:减少不在同一模块内元素之间的关系,增加在同一模块内元素之间的关系;联结(Binding)是衡量内聚的度量值。n 类型(由上至下越来越差好,第一个最差,后两个最好):u 偶然(Coincidental):没有Binding,语句凑巧放在一起u 逻辑(Logical):通过逻辑相似性binding,比如都是编辑,典型的例子:如果是A,则按A规则编辑;如果是B,则按B规则编辑。u 时序/临时(Temporal):通过逻辑相似性和时间binding,即元素间有时序关系,典型例子:初始化或终止方法u 通信(Communicational):其实与时序比较没有很明确的优劣关系;通过逻辑相似性和数据binding,元素间共用数据u 顺序(Sequential):解决同一个问题来binding,一个元素的输出是另一个的输入;比上面的耦合都好,因为Same的比Similarity的binding强u 功能(Functional):通过共同的一个目标binding,所有元素与一个功能相关,最好的内聚;典型例子:计算平方根,最短路径问题,压缩数据库;适用于N:M问题u 信息(Informational)n 类型判断方法:用一句话描述模块,复合语句动词数大于1,多于一个功能,很可能是交互或顺序;有时间词语“第一”、“接着”等等,很可能是顺序或者时序;没有单一目标,很可能是逻辑。(2) 面向对象的耦合类型;l 类型n 交互耦合(Interaction Coupling) u 单交互耦合,两个类之间的方法调用或者属性使用,与经典的模块间耦合定义最相似,不包括继承,参数和属性不包括类的形式。n 组件耦合(Component Coupling):一处定义多处使用,类和对象级别,一个类作为另一个类的实例变量使用,不包括继承,通常是类级别。u 四种组件耦合形式:完全变量(Whole variable)聚合(Aggregation);参数方法参数;创建者某个方法的局部变量;隐藏另一个对象提供;l 隐式的(Hidden)组件耦合:最坏的耦合,隐藏的组件耦合指一个对象没有出现在规格说明和实现中,但是却在另一个类的方法使用中被使用。这种情况的典型例子就是方法返回值直接被用作另一个方法的参数不允许串联(cascading)消息的使用。n Demeter法则:类可以使用本身,可以使用自己的成员变量,可以使用被给予的对象,可以使用自己创建的对象l 分散的(Scattered)组件耦合:一个类在另一个类实现中定义某个局部变量或者实例变量的时候被使用,但是没有出现在这个类的规格说明中;聚合全局,局部实例局部。l 说明的(Specified)组件耦合:每当一个类作为另一个类的组件时,都会包括在这个类的规格说明中;Design by Contract,提供(Suffered)的接口说明的,需要(Required)的接口使用的n 继承耦合(Inheritance Coupling):父类的信息对于子类来说是Specified;有父类引用时,子类可以修改、精化、扩展u 修改(Modification)继承耦合:不按规则和限制的修改,最坏的继承耦合,对多态有害,如果Client使用父引用,父子方法都需要;这种耦合式隐式的,有两个连接,更复杂u 精化(Refinement)继承耦合:定义新的信息,继承的信息仅根据定义好的规则改变;Client使用父引用,整个父的部分和子的精化是需要的,1+个连接;这种耦合是必须的u 扩展(Extension)继承耦合:子类只是增加方法和成员变量,没有修改也没有精化继承的那些;Client使用父引用,只有父需要;1个连接u 继承降低耦合:精化和扩展继承耦合中,父子类间的交互耦合忽略;这样对象级别的耦合存留,但是类级别耦合减少了n 类间的耦合度量(不是重点,应该不考):u Coupling between object classes(CBO),越低越好,计算一个类A中其他类的数量,这些类满足以下条件l 使用A中的方法或变量或包含A使用的方法或变量l 不包含继承u Response for a class(RFC):(方向(Direction)很重要)一个对象接受一条消息后可能会有响应的方法的数量,不包括继承,包含嵌套的方法调用,越低越好u Message passing coupling(MPC):一个类局部位置定义的发送(send)语句的数量,越低越好;这个指数指示局部方法对其他类的方法的依赖程度u Data abstraction coupling(DAC):拥有依赖于其他类定义的ADT类型的属性的数量,越低越好u Ce and &D(efferent and afferent coupling):输出输入耦合,越低越好u Depth of the inheritance tree(DIT):从节点到树根的最长路径长。DIT增长,由于继承深度增加,则类的行为更难预测;正面效应DIT大表示许多方法可能被复用u Number of children(NOC):直接附属于子类的父类的计数;NOC增加,则复用增加,抽象被淡化,测试量增加(3) 对给出的例子:l 判断其内聚和耦合的类型,并将其修正为正确的类型。l 分析其Connection类型,计算不同Connection类型的数量。3. 信息隐藏l 最有可能改变的设计领域n 硬件依赖n 输入输出格式n 非标准语言特性和库函数;n 困难的设计和实现领域n 复杂数据结构,被不止一个类使用的数据结构,或者你还没有得到满意设计的数据结构n 复杂逻辑n 全局变量n 数据大小限制,例如数组声明和循环限制;业务规则;计算机系统嵌入过程(1) 对简单的应用,按照“处理流程”与“信息隐藏”两种方式分别给出设计描述。l 典型例子:KWICn 处理流程(功能)n 信息隐藏:l 比较:n 一般性比较:两个系统可能使用相同的数据结构和算法,区别在于他们划分成工作单元的方式;即使在可运行的表示上是相同的系统本质上也不同,其他表示有变化、文档化和理解n 可变性比较:设计决策变化,模块化2普遍表现较好n 独立开发:模块化1必须先设计好所有数据结构才能开始并行开发,需要复杂的描述;模块化2必须设计好接口才能开始并行开发,仅需要简单描述n 可理解性:模块化2比较好,主观判断和针对接口编程(2) 对简单的应用,解释其Module Guidel Module Guide:层次式结构化文档;帮助开发人员和维护人员找到变更影响到的模块;n 模块化结构的目标:每个模块的结构应当可以简单到全部理解;要改变一个模块应当不需要知道别的模块的实现也不会影响其他模块的行为;一个较大的软件变化应当可以通过一系列单独模块的独立变化实现;软件工程师应当在不了解内部实现的情况下了解模块的职责;有良好定义的关注点应当能够在不研究无关模块的情况下容易的确认相关模块;n 对于每一个模块,Module Guide陈述:u 每个模块关联的secrets:Primary Secret软件设计者专有的隐藏信息,Secondary secret实现隐藏PS的模块时做出的实现设计决策u 在整个系统运作中单个模块所扮演的角色u 每个模块提供的facilitiesn 例子:模块化层次,模块按照其secret类型的不同进行组织;第一层,Hardware,behavior,softwaren 利用文档的设计(Design through Documentation):增加了产品完整性和软件可复用性的可能性u Module Guideu Module Interface Document:与MG不同,包含精确完整的模块接口描述u Module Design Document:模块每个实现的内部实际文档u Requirements Document:MG引用该文档来有关的变更4. 软件体系结构风格l 软件体系结构风格定义:用结构化组织的模式来定义一系列系统,并定义组件和连接件的vocabulary以及其如何结合的限制;描述一类体系结构或重要的体系结构片段,实践过程中被重复发现,是一组紧密相关的设计决策,具有允许重用的已知属性l 不同组件的风格:对象(设计模式)、模块、进程、物理单元n 模块风格:n 进程风格(1) 描述或比较相关风格 模块风格l 描述点:简要规则流程叙述,组件连接件和限制是什么,优缺点,适用系统;比较点:算法变化,数据表示变化,附加特性(功能),性能空间时间,复用l Call-and-Returnn Main-program-and-subroutine:层次式分解程序,单线程控制,子系统结构隐藏,每个组件接受父组件的控制;组件是过程、函数或者模块,连接件是他们之间的调用,限制是控制始于调用层次的顶层然后向下移动;过程清晰易于理解,正确性控制强,变更和复用困难,可能是公共耦合,适用顺行系统和正确性攸关系统n Object-oriented(数据抽象):通过封装数据表示和相关的操作帮助提高修改性,对象保证自己数据表示的完整性,每个对象都是匿名的代理,只能通过固定格式的过程调用来使用对象;组件是对象或模块,连接件是函数或调用;在不影响使用者的情况下可以修改实现,系统分解为一系列匿名代理,但一个对象要与另一个对象交互必须知道对方的标识符,并且会有副作用问题,从而产生不可预期的操作,适用于有一个中心问题并须保护相关信息(数据)的应用l Pipe and Filter:每个过滤器处理数据然后传递给下一个过滤器,每当有数据需要处理时过滤器都会运行,数据共享严格控制在管道的传递上;组件是过滤器,连接件是管道,限制是过滤器之间不共享状态,过滤器不知道上下游的标识符,输出正确性不依赖于过滤器顺序;适易于理解,支持重用,维护和增强容易,允许特定种类的专门分析,支持并发,交互不佳,需要额外空间,解析增加性能流失和过滤器编写的复杂性,用于在有序数据上定义一系列独立计算的应用;特化形式n Pipelines(线性拓扑)和Batch Sequential(pipeline退化版)l Implicit Invocation:组件发起一至多个事件,也可以注册某个方法来响应某个事件,当时间发生时,连接件调用所有注册该事件的方法,封装共享数据,避免暴露存储格式给计算模块,数据更改时计算被隐式调用,典型应用事件;组件是agent(对象,过程,进程),连接件是广播中介(事件处理器),限制是事件发起者不知道事件影响那些组件,无法假设处理顺序以及处理结果;复用支持极佳,系统演化容易,但难以保证正确性和完整性,且测试和诊断困难,适用于拥有松散耦合的组件集、每个都可能执行一些使其他组件进行处理的操作的应用l 上面四种比较Main-program-and-subroutineObject-OrientedPipe and FilterImplicit InvocationChange in algorithmBadMediumGoodGoodChange in data representationBadGoodMediumMediumChang in functionsMediumMediumGoodMediumMake system interactiveMediumMediumBadMediumSpace performanceGoodGoodBadGoodTime performanceBadBadMediumGoodReuse componentsBadMediumGoodGoodl Repository(Blackboard):组件是一个表示系统正确状态的中心数据结构,一组操作中心数据结构的独立组件(agent),连接件是过程调用和直接内存存取,限制是所有agent应当独立并且依赖共享数据,检查数据状态并做出反应(Pull vs. Push);存储大量数据的方便方式,集中化管理,必须先对数据模型达成一致,中心数据体会成为瓶颈,数据演化昂贵,适用于中心问题是建立扩充和维护阻隔复杂中心信息体的应用n Repository vs. Blackboard:前者使用pull模型,易于实现但客户端复杂并且需要轮询数据;后者使用push模型,客户端编程简化但需要复杂的结构l Layered:组件是一组过程或对象,连接件是过程调用和限制可见性的方法调用,限制是系统组织成层次结构,每层给上层提供服务并作为下层的client,跃层是不允许的;设计基于不同层次的抽象,更改一层最多再影响两层,同层可互换提供服务增强复用,但不是所有系统都有明确的层次结构,并且性能可能会需要跃层访问以及实现部分访问,适用于拥有明确的服务种类从而可层次式组织的应用,例如层次式通信协议和操作系统,特例是异常一般是无层次直接交互的l Model-View-Controller:model子系统设计为不依赖任何view子系统和controller子系统,其状态的变化会传递给view子系统;model组件负责维护领域知识和通知view变化,view组件负责显示信息并传递用户指示给controller,controller负责更改model状态和选择响应view,连接件是过程调用、消息、事件、直接内存存取;允许一个model上建立多个独立view,view可同步,可“插拔”(易于修改)的view和controller,但增加了复杂性,view获取数据效率不高,与流行UI工具不十分兼容,适用于UI修改容易并且可以运行时修改、UI的修改不应该影响功能部分设计和代码的应用l 比较 进程风格l Point-to-point:消息被发送给一个唯一可确定的接收者,空间上双方需要互相了解,时间上必须是同步激活l Publish-Subscribe:多个应用接受相同消息,发布者和订阅者松散耦合,消息传送基于事件发布,事件类型层次化组织;组件是发布者和订阅者,连接件是事件Router复杂并且负责失败; 物理单元风格l Client-Server:分布式系统的特例;组件是client,连接件是RPC-based interaction protocols;server不知道client的数量或identities,而client知道server的identityl Three-Tier(N-Tier):表示层(接口层或前端)、应用业务逻辑层、数据层(存储层或后端),像是在client/server间再加一层,提供了用户接口和业务逻辑的分离l Peer-to-Peer:client/server的泛化,更难实现;组件是匿名的既作为client又作为server,连接件是同步或异步消息传递但一般不共享内存,交互的拓扑结构差异性和动态性较大l Distributed Systemu Distributed Objects(middleware)u Distributed Resources(http)u Distributed Services(web service)u 比较l5. 全局分析的步骤l 软件体系结构设计的两个基本部分:设计描述系统结构使用四个互补view来减少体系结构设计和理解的复杂性;第二部分是全局分析产生描述上下文和设计决策理由的文档。将两个部分集成,由一个初始的view框架开始设计,从而做出决策l 全局分析步骤:n 识别影响体系结构的外部影响因素和关键需求1. 分析因素(constraints和质量),分三步a) 识别并描述因素,分为产品(系统质量)、组织(业务质量)和技术(系统和业务)三大类b) 描述因素,叙述这些因素的flexibility(别的因素变)和changeability(自己变)特征c) 分析因素的impact(自己变),相关的因素以及影响范围2. 开发策略,分三步a) 识别issue和有影响的因素,将因素与问题关联,分析限制和约束b) 开发解决方案和特定的策略c) 识别相关策略n 分析他们,得出设计体系结构的策略6. 根据分析类图,建立基本的设计类图l 转换领域模型:将角色转变为接口类;添加角色domain类;添加启动类;转换或添加控制器和协调器;添加数据类型类;转换或添加容器类;转换或添加工程设计关联l 分配职责:操作职责通过操作满足,数据职责通过属性满足,有类协作n 职责驱动的分解:帮助实现高内聚低耦合,确保模块职责不重叠,只有操作或数据对完成模块职责有益时才将其放入该模块,一个模块完成职责所需全部操作和数据都应放于该模块l 继承是一个类和一个或多个超类之间的关系,子类有超类的每个属性和操作n 不要仅仅为重用使用继承n 只有当有泛化关系(kind-of)的时候才使用继承n 可以重新考虑类结构来实现重用l 代理:一个模块将职责委托给另一个,在不违反继承约束的情况下允许了重用,增加了重用、灵活性和可配置性7. 有几种控制流处理方式?进行比较l 控制器:做出决策并指导其他组件的程序组件,因为他们在交互中的中心地位而十分重要l 控制启示:避免大部分消息产生于一个单一组件的交互设计;保持组件小型;确保操作职责不仅仅分配给少数组件;确保操作职责与数据职责一致;让组件代理尽可能多的低层任务;避免需要每个组件发送许多信息的交互l Demeter法则:一个对象obj的操作只应当向以下实体发送信息:obj,obj的属性,该操作的参数,所属集合为该操作的参数或者obj的属性的元素,该操作创建的对象,全局类或对象l 控制风格(Control Styles):决策制定在组件之间分布的方式;有以下几种n 集中式(Centralized):少数控制器做出所有重要决策。容易找到决策制定的位置找到,也容易明白决策如何制定以修改决策制定过程;控制器可能会膨胀,会变得大而复杂,难以理解、维护和测试等;控制器可能将其他组件视为数据存取部件,这将增加耦合,破坏信息隐藏n 委托式(Delegated):决策制定分散在程序中,少数控制器做出重要决定。控制器与少数组件耦合,信息隐藏更好,程序容易分层;这种风格是较为推荐的n 分散式(Dispersed):决策制定广泛分布在程序中,少数(或没有)组件自己做出决策。有许多具有小数据少量职责的组件,难以理解控制流,组件本身无法完成很多工作从而增加耦合,难以隐藏信息,低内聚,不太满足模块化原则8. GRASP模式l GRASP:是General Responsibility Assignment Software Patterns的缩写,这些模式不是设计模式,而是对象设计的基本原则,关注对象设计最重要的方面分配职责给类,并不强调体系结构的设计;l Expert(专家模式):最基本的问题谁负责得知某些信息;解决方法将这个职责分配给需要信息来完成自己职责的类;维护信息封装,低耦合高内聚,可能使类变得很复杂l Creator(创建者模式):问题谁负责创建某类的新实例;解决方法赋予B创建A的职责如果(B聚合A,B包含A,B记录A的实例,B密切使用A,B有创建A的初始数据),其中第一条或第二条最好;类拥有创建需要引用的对象的职责来减少Connection以降低耦合,自己创建实例可以避免依赖于其他类为条目创建实例l Low Coupling(低耦合):问题低依赖度、高复用性;解决方案分配职责保持低耦合;类易于维护和复用,变更本地化l High Cohesion(高内聚):问题使得复杂性在可管理的范围内;解决方案分配职责保持高内聚,一个功能领域的中等规模职责,与其他类协作完成任务;类易于维护和理解,增益低耦合,职责粒度适中故而为复用提供支持;n Rule of thumb(首要原则)l Controller(控制器):问题谁负责处理系统事件;解决方案如果程序接收不是从图形接口来的外部源事件,添加一个事件类来解耦事件源和处理事件的对象;将处理系统事件消息的职责分配给类(业务或者全局组织facade controller,全局“系统”facade controller,领域中执行工作的活动体,人工类型(纯虚构)use case controller);增加了复用的可能性,将外部事件源和内部事件处理的类型和行为独立开,论证用例的状态,确保系统操作以合法的顺序出现,或能论证用例中活动和操作的现状态;使用Controller对象保证外部事件源和内部事件处理的类型和行为独立开,拥有更多的职责controller对象可能高耦合低内聚l Polymorphism(多态):问题谁处理基于类型的多个选择;解决方案基于类型有多种行为选择时,使用多态方法调用来选择行为而不是使用if语句来测试类型;比显示选择逻辑更简单和可靠,更易于增加附加行为,但增加了设计中类的数量,也使得代码更难跟踪l Pure Fabrication(纯虚构):问题如何不违背高内聚低耦合;解决方案将高内聚职责结合分配给在问题域中没有对用的人工类,只有状态或只有行为,从而支持高内聚低耦合和复用;由于职责被分配给关注一个非常特化的相关任务集的类而得到高耦合,适中粒度的纯虚构类增加复用的可能性;例子,操作数据库的类,适用场景分离表示层和模型层、分离平台(facilities)和模型层、分离复杂行为或复杂数据结构l Indirection(间接):问题如何避免直接耦合、解耦对象以支持低耦合和高复用可能性;解决方案将职责分配给一个中间对象来协调其他组件或服务,使他们不会直接耦合;与可变性解耦,提升复用l Protected Variations(差异性保护):问题如何设计对象、子系统和系统以便这些元素的差异性或不稳定性不会对其他元素产生非预期的影响;解决方案识别可预期的差异点和不稳定点,分配职责以创建一个稳定的接口;信息隐藏,数据驱动(配置文件),服务lookup(运行时注册),interpreter驱动(泛化模块),映射或元数据级别设计(组件代替),统一存取(协议依赖),LSP(多态),Demeter法则(限制交互路径)(1) 对外部事件交互,应该如何处理?l 示例ll Good design: presentation layer decoupled from problem domainl Bad design :presentation layer coupled to problem domain(2) 对给定场景,判断职责的分配9. 设计模式(1) 普通Programming to Interfaces有哪些手段?l 集合l 继承:允许定义一系列接口一样的对象,导出类共享基类接口,所有子类使用抽象类的接口响应请求,继承树上的类算一个耦合n LSP:所有导出类必须可作为其基类的代替(2) 集合类型Programming to Interfaces有哪些手段?l 迭代器模式n 目的:提供一种顺序存取聚集对象的元素又不暴露底层表达的途径;支持聚集对象的多重遍历,为遍历不同的聚集结构提供统一接口(支持多态的迭代)n 结构n 成果u 针对接口编程,信息隐藏u 支持遍历聚集的差异性u 简化聚集的接口u 一个聚集可以有多于一个遍历n 迭代机制设计方案控制:外部迭代控制和内部迭代控制(更好)l 代理模式n 问题:为另一个对象提供对其进行控制存取的代理或中介u Remote Proxy:为不同地址空间的对象提供本地表示u Virtual Proxy: 按需创建、也可能缓存昂贵的对象u Protection Proxy:控制对原始对象的存取,当存取权限不同时有用n 结构u Subject为抽象类/接口,RealSubject和Proxy继承Subject,client永远使用的是Proxy,Proxy负责代理安全的调用,如果不安全调用出现就会有异常或警告n 成果:引进存取对象的一层间接l 原型模式:使用原型实例指定创建的对象种类,通过复制原型的方式创建新对象n 结构(3) De-Coupling有哪些手段?l 避免重复只做一次:重复往往代表着耦合,修改一部分重复代码表示要修改其他的l DIP:Dependency Inversion Principle,依赖倒置原则,即细节应当依赖于抽象,抽象不应当依赖于细节;在要被其他模块implement的模块中定义接口,这是一种去除依赖减少耦合的基本方式l 继承:共性和差异性l 设计模式n 中介模式u 问题:一组对象以良好定义但复杂的方式交互,通常为非结构化的依赖;由于与许多对象的引用和通信对象复用困难;分散在几个类中的行为应当在子类不多的情况下自定义u 结构l Mediator定义了Colleague通信的接口,通常被告知某个事件或情况了;每个Colleague知道其Mediator,需要交互与Mediator交互,向Mediator提供服务/请求,有对所有Colleague的共同请求,也有特化的u 成果l 定义封装一组对象交互方式的对象;中介通过避免对象互相显式引用提升了松散耦合;让你独立的差异交互;集中控制n 桥接模式u 问题:处理一个抽象多个实现的普通手段是继承,然而这将实现与抽象永久绑定;这样做不够灵活,可能需要单独分别修改或者扩展抽象和实现u 解决方案:分离抽象类层次和实现类层次,使用代理作为二者的桥梁实例u 成果:解耦了接口和实现消除了编译时依赖,改善了可扩展性,对client隐藏了实现细节(4) 一个模块的信息隐藏有哪两种基本类型?l 基本secret:外部行为vs.内部实现,隐藏一个重要的设计决策的实现细节,只有该模块的元素才知道该细节l Facade Design(门面)模式n 问题:针对模块/子系统的一组接口提供统一接口,定义高层接口使得模块/子系统更易于使用n 解决方案n 成果:信息隐藏,解耦了组件的一个子系统和一个clientl 附加secret:改变,隐藏对于预期的改变,把可能改变从模块中分离开来,安排到新的类,方法或者设计单元中,使得这个可能改变的设计单元不会影响其他部分l OCP:Open-Closed Principle,一个软件实体应当对扩展开放,对修改关闭l 策略模式:将算法从包含其的对象中抽离出来,封装该算法(策略)为一个对象n 结构使用桥接模式来解决context也是可变的l 装饰模式:装饰在不改变类的代码的情况下扩展了一个类的实例的功能,比静态继承更灵活,装饰者在幕后工作,对接口是透明的n 解决方案n 成果比静态继承更灵活,避免功能负担重的类在层次中位置高,有许多相像的小对象,难以理解和调试,装饰者和组件不一样,所以检查对象一致会引起问题l 适配器模式:将类的接口转换成另一个client期望的接口,让接口不兼容的类能一起工作n 解决方案(5) 实现共性与可变性有哪些手段?l 多态(继承)1 of N:父为共性,子为差异性l 聚合M of N:整体为共性,部分为差异性;在复杂场景中聚合更好l 运行时注册1 of N/M of N:静态编译为共性,运行时注册为差异性l 策略模式n 问题:当许多相关类仅在行为上不同时使用策略模式提供在许多行为中配置一个类的一种行为;一个类以操作中的条件语句的形式定义许多行为时可以使用策略模式;当你需要不同算法变种时使用;一个算法使用了client不应当知道的数据;当在固定的特性中有可变的行为时使用n 解决方案n 成果:可变性和复用性,复杂,消除了条件语句但分离了逻辑,client必须知道有不同的算法l 状态模式n 问题:对象的行为依赖于状态,操作有许多可选结构每个状态有不同的选择n 结构n 协作:Context代理状态State的特殊请求,将自己作为参数传递给ConcreteState对象,client只需与Context交互,可以决定是哪个ConcreteState对象n 成果:本地化状态敏感的行为,易于添加新状态但增加了类结构的大小,使状态转换显式消除了潜在不一致的内部状态,状态对象能被共享l 运行时注册和Call-backsn Callback是可注册给server的client方法,server可进行调用,实现扩展性的机制,作用在server对象的中间状态上l 观察者模式n 问题:定义对象间的一对多关系,当一个对象改变状态时,所有它的依赖者都被通知并自动更新n 解决方案n 成果:灵活,可变,复用,低耦合,但更复杂,更难理解和测试n 当遇到以下情形之一时使用此模式:一个对象改变需要改变别的,不知道需要改变多少;一个对象在不知道对方是谁的情况下要能够通知其他对象,松耦合l 命令模式n 根据对象的动作参数化对象,然后在不同时间指定、排列、执行请求,保存上下文信息支持undo,支持恢复目的的变更日志n 解决方案n 成果:解耦请求的接受者和执行者,可以使用堆栈或队列保存命令,易于支持undo和redo,更易于扩展命令(6) 对象的创建有哪些常见解决方法?l 与其他对象的创建connection:无限制的实例,创建类型,简单实例化和初始化l 方法有:Creator模式、Coupling模式、Cohesion模式l 场景1:只有一个实例n 单件模式u 问题:有时我们只需要一个特殊类的一个实例,为安全起见多于一个即非法u 结构l 场景2:有限个实例l 封装对象创建n 工厂:一个职责为创建不同类型类的类n 更复杂的场景:类型差异知道要创建实例但不知道哪种被创建n 工厂方法:不是简单工厂;定义创建对象的接口,但让子类决定实例化哪个类,将类延迟创建到子类n 抽象工厂u 问题:目的是提供在不指定concret类的情况下创建一系列相关或依赖的对象的接口u 解决方案u 成果:隔离了concret类,容易更换产品系列,保证产品间的一致性;很难支持新品种的产品,不得不重新编写抽象工厂和所有子类,但是在动态语言中这并不是那么坏的事l 场景3:复杂的实例化和初始化,例如运行时实例化和初始值差异n 原型模式:使用原型实例指定要创建的对象种类,然后使用原型拷贝来创建新对象u 结构u 成果:运行时增加和去除原型,通过不同的值指定新对象(添加新原型),伪动态装载(7) 设计模式部分所有的思考题1. 寻找一个需要访问集合变量的场景;编程实现:Iterator Pattern和Proxy Patternn 假想一个场景,需要通过迭代器来访问元素的后继(Binary Tree);BinaryTree 类实现基本的二叉树的插入查找等功能,这里不再给出;测试用的Main也不给出了n 下面给出迭代器,主要实现基本的访问功能01 public class BinaryTreeIterator 02 Object index;03 BinaryTree bt;0405 public BinaryTreeIterator(BinaryTree bt)06 this.bt = bt;07 index = bt.findMinNode(bt.head);08 0910 public Object first()11 return bt.head;12 1314 public void next()15 index = bt.successor(Node)index);16 1718 public boolean isDone()19 return index = null;20 2122 public Object currentItem()23 return index;24 25 n 代理模式,封装一部分操作01 public class BinaryTreeProxy 02 private BinaryTree bt;0304 public BinaryTreeProxy(BinaryTree bt)05 this.bt = bt;06 0708 public void insert(int element)09 bt.insert(element);10 1112 public Node searchNode(int x)13 return bt.searchNode(x);14 1516 public Node findMaxNode(Node node)17 if (node = null)18 return null;19 20 if (searchNode(node.getElement()= null)21 return null;22 23 return bt.findMaxNode(node);24 2526 public Node findMinNode(Node node)27 if (node = null)28 return null;29 30 if (searchNode(node.getElement()= null)31 return null;32 33 return bt.findMinNode(node);34 3536 public Node successor(Node x)37 if (x = null)38 return null;39 40 if (searchNode(x.getElement()= null)41 return null;42 43 return bt.successor(x);44 45 2. 用Mediator模式实现CardShark游戏(P467)n 每一个Colleague继承一个基类,参与者有cardsender、player、container,这些参与者需要交互的方法都是得到自己的mediator再调用mediator的方法完成的n 容器的状态类3 public enum status 4 Null,PutStack,Gambling,End5 n 调停者(Mediator),集中式控制,保存需要通信的参与者引用,重要的方法registerXXX(注册一个参与者),noticeXXX(一个动作)3. 实现前面Bridge Pattern的示例4. 考虑实验中你所负责的模块,是否需要利用Faade模式Just for fun,不考5. 利用Decorator解决下图的新增功能public class WritePrinter public void write(int c)public abstract class Decorator extends WritePrintprivate WritePrint wp;public void setWritePrint(WritePrint wp) this.wp = wp;Overridepublic void write(int c) public class WriteDisk extends Decorator Overridepublic void write(int c) if (wp != null) wp.write(c);6. Adapt enumeration to iterator(接口见右图)n 下面为Adapterpublic class Adapter implements Iterator private Enumeration enumeration = new ConcreteEnumeration();public void hasNext()enumeration.hasMoreElements();public void next()enumeration. nextElement();public void remove()/无法实现,只有接口7. 1)如果一个对象集的一个行为需要协作对象来完成,但是它们在协作对象上存在差异性,如何处理?将与其他对象连接的部分分离出去2)如果一个对象集之间除共性外,有超过个的差异行为,如何处理?每个行为都封装出去3)如果一个对象集除了接口之外,全是差异行为,如何处理?保留接口,其他全部做成策略4)从共性和差异性角度,如何解释Bridge模式?(Bridge非常典型的只有Interface)暴露给Client的是不变的接口,Abstraction和Implementor给出了一些共同操作的接口,但Abstraction可以有不同的实现,实现也有不同的实现。Abstraction是共性,Implementor是差异性,但是对于一个继承树接口是共性,而实现是差异性,利用了继承和聚合。8. 比较strategy 与 statea) 1 of N or M of N?策略模式用在M of N 的情况下;状态模式也可以,但是通常用在1 of N 的情况下。b) Who control the changing?谁控制修改是不固定的,谁拥有改变规则就控制修改。参考信息专家,将职责分配给拥有足够的信息去完成整个职责的类。例如,状态模式:Context变量放在哪个里面,哪个就可以控制修改。c) How to change?i. Fixed rules or table-driven (configuration files)按实际情况:如果需求可以固定为固定的规则,则用fixed rules;如果是外部控制需求改变,则是table-drivend) Creating and destroying policy?视具体情况而定,一般是在ref那里创建n 比较u 在状态模式中,状态的变化是由对象的内部条件决定,外界只需关心其接口,不必关心其状态对象的创建和转化;而策略模式里面,采取何种策略由外部条件决定的。u 其实,两种模式的关键不同在于,状态模式注重给客户对象提供在不同状态间切换不同的行为。重在切换;而策略模式注重给客户对象提供多种不同的选择,一般来说,用户不会经常切换来切换去。u 在现实世界中,策略(如促销一种商品的策略)和状态(如同一个按钮来控制一个电梯的状态,又如手机界面中一个按钮来控制手机)是两种完全不同的思想。当我们对状态和策略进行建模时,这种差异会导致完全不同的问题。例如,对状态进行建模时,状态迁移是一个核心内容;然而,在选择策略时,迁移与此毫无关系。另外,策略模式允许一个客户选择或提供一种策略,而这种思想在状态模式中完全没有9. “Context decide changing of ConcreteState object ”与“ ConcreteState decide changing of ConcreteState object”有何不同?前者是指用context来操作不同状态类的自动转换,后者是指用具体某个状态的某个event来自动实现各个状态之间的跳转。10. 以singleton为基础,编写程序解决Limited instance permitted问题/实例的状态Public enum Status Busy,/被客户占用Free/空闲态public class SingletonN private Status status;private static ArrayList ins
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 大学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!