1、1 名词解释:1.1 设计的5个准则1.2 4+1 View1.3 OO协作与协作设计1.4 OO职责与职责分配1.5 GRASP模式(或其中之一)2 软件设计的审美标准有哪些?列举已知的软件设计方法与技术(至少5种)并说明它们促进了哪些审美标准的达成?3 设计的层次性高层设计、中层设计和低层设计各自的出发点、主要关注因素(即哪些审美要素)、主要方法与技术和最终制品4 软件体系结构风格(1) 描述或比较相关风格(2) 对给定场景,判断需要使用的风格4.1.1 模块级别n 调用返回风格 主程序子路径:部件从其父部件当中得到控制信息,绝不向其同级或上级发出调用信息。部件:过程、功能和模块。连接键:
2、程序调用。约束:控制流总是由顶端延层次结构开始向下传递。 面向对象式:对象能够帮助进行封装内部的secrets,只有通过方法才能够访问对象。部件:对象或模块连接键:方法调用约束:数据的表示对其他对象来说是透明的;每个对象的数据完整性自行维护,每个对象是独立的。 管道过滤器:每个Filter都能处理数据然后传递给下一个Filter,Filter可以在任意处处理数据,各个Filter之间无数据共享,通过Pipe交互。部件:Filter连接键:Pipe约束:Filter之间不共享数据;Filter并不了解上下Filter;单个Filter的正确性并不依赖上下的Filter 层次风格:描述层与层之间的
3、调用结构。部件:过程或对象的集合连接键:过程调用或方法调用约束:系统要被严格组织成层次结构,每一层为其上层提供服务,并调用下一层,不允许跨层调用。 比较n 主程序和子路径中算法和数据结构式绑定的,修改算法差;如果要修改数据,则需要所有的模块进行更改差;增加功能到系统中,要修改一个部件居中;空间性能很好,数据时共享的,时间性能差,不存在并发处理;重用性不好,所有模块都与数据进行绑定优点:处理过程清晰,易理解;能够保证正确性缺点:不利于更改和复用;处理不当会形成公共耦合适用:顺序处理系统;正确性要求较高的系统n 面向对象式在算法修改居中,只要不涉及接口可以随意进行修改;数据表示修改优,数据在接口中
4、隐藏了;增加新功能到系统中居中,需要对现有模块进行修改;空间性能很好,在方法调用中可以共享数据,时间性能差,不存在并发;可复用性居中,接口依赖。优点:只要不修改接口,模块之间的可修改性很好;系统被分解为许多独立的部分缺点:对象之间交互必须了解对方的接口;对象可能产生副作用适用:能够把系统分解为算法+数据的结构,以进行封装n 管道过滤器在算法修改优,Filter之间完全独立;更改数据表示方式居中,只会更改存在的Pipe;在增加新功能优,通过增加新的Filter实现;空间性能差,Filter之间没有共享数据,需要对数据进行拷贝,时间性能优,存在并发,但是拷贝数据可能会花费时间;可复用性优。优点:易
5、于理解,支持复用,易于维护和扩展,对于特殊的要求可以满足,支持并发。缺点:不能很好的处理交互问题,传输数据需要额外的空间,可能丢失额外的性能并增加复杂度适用:系统可分解为多个可并行的任务n 层次结构优点:基于增加抽象层次设计;易于修改;易用重用缺点:很多系统无法简单的划分层次;必须按层次调用,增加高层和低层实现之间的耦合适用:系统可以按照功能划分为不同的层次n 隐式调用风格(基于事件)u 数据封装,所有调用通过事件完成部件:agent连接键:事件处理约束:抛出事件的部件不了解被影响的部件有哪些;对事件的接收顺序也不能有假设;不能假设事件抛出一定有部件进行处理 u 不需要共享数据,算法修改优;共
6、享数据进行封装,但是仍然存在,数据表示更改居中;添加新功能居中,需要修改现有的模块;空间性能优,数据是共享的,时间性能优,存在并发性;可复用性优,只要是处理特定的事件都可以进行复用。优点:可重用性好,可修改性好缺点:正确性得不到保障;调试测试会很困难适用:通常适用于能把系统分解为松散耦合的系统n 黑板风格:u 各个客户端读写同一块存储区域部件:一个中心数据结构表示系统状态,一系列独立部件含有在中心数据结构上的操作。连接键:过程调用或直接内存访问约束:所有的agent都是独立的;每个agent都依赖共享数据;agent对数据进行操作。u 优点:可以充分存储大量数据,空间性能优越;减少复杂数据的复
7、制缺点:必须能够建立稳定的中心数据区;Blackboard可能会成为瓶颈;数据的演化代价很高适用:可以建立一个中心数据区,并且维护复杂的中心信息。n MVC风格u Model与Controller、View分离。部件:Model部件用来维护领域信息,通知View的更改;View 部件用来给用户展示信息,发送用户请求到Controller;Controller部件用来更改Model状态,对用户请求响应。连接键:系统调用、消息、时间、直接内存访问u 优点:允许多态,在一个模型中有独立的View;Views能够被序列化;可以任意增加删除View和Controller缺点:增加了复杂度;在View中不
8、能有效获得数据访问;与现代用户界面工具不是特别兼容适用:接口的更改很容易并且可能发生在运行时;用户界面的修改并不会影响逻辑代码4.1.2 进程级别n 点对点风格(Point to Point)u 分布式系统中异步消息SenderReceiverMessage QueueScheduleru 可能多个应用程序需要接受同一个消息;发送者和接受者之间的松散耦合的;传输是基于事件接受的;事件存在层级结构u 部件:发送者、接受者连接键:事件路由4.1.3 物理单元n C/S风格u 部件:Client、Server连接键:基于RPC(远程过程协议)交互协议n 三层结构风格u 包括表示层、业务逻辑层和数据层
9、n 端对端结构风格(Peer to Peer)u 部件:部件即作为Client也作为Server连接键:同步异步消息;不共享内存u 无法区分Client和Server,要了解所有的设备n 分布式结构风格网络上所有的物理节点都是平等的,使用时透明。5 职责分配与协作设计(3) 协作设计(控制风格)的比较和场景判定(4) 对给定场景和要求的控制风格,根据GRASP模式,判断特定职责的分配(5) 根据分析类图和体系结构模块接口,建立基本的设计类图6 设计模式6.1 普通Programming to Interfaces有哪些手段?l 代理模式问题:为另一个对象提供一个代理或占位符以控制对这个对象的访
10、问分类:远程代理为不同地址空间的对象提供了本地代表,有可能需要重编码请求 虚拟代理按需创建开销大的资源,may also cache 保护代理控制对原始对象的访问,当访问权限改变时比较有效类图: 合作:n 三个类: Subject, RealSubject, and Proxy.n Client操作Subject中的接口n RealSubject, and Proxy实现Subject的接口n Proxy如果发现危险动作,如Writing collections动作,就会发布异常或者报警n Proxy将安全的调用委派给 RealSubject.n Client 始终使用 Proxy. 结果:
11、引入了操作对象的一种间接方法q remote proxy可以隐藏地址空间差异q virtual proxy 可以优化 q 允许附加的管理l 原型模式使用原型实例来实现创建对象,通过拷贝原型的方式图示:参与者: 原型 声明了一个克隆自己的接口 具体原型实现了克隆自己的操作 客户 通过克隆原型创建对象a) 迭代器模式:提供一种方式来访问一个集合,但不用了解其内部的数据结构。i. 优点1. 可以实现针对接口编程和信息隐藏2. 可以实现集合的不同遍历方式3. 迭代器简化了聚合的接口4. 可以同时有多个迭代器的存在ii. 迭代机制:内部迭代和外部迭代b) 代理模式:为另外一个对象的控制访问提供一个替代,
12、包括远程代理、虚拟代理、安全代理。i. 远程代理能够隐藏对象在不同地址空间的事实ii. 虚拟代理可以达到优化iii. 安全代理允许额外的安全保障c) 原型模式:当使用原型对象创建某个类型的对象时,通过返回这个原型的拷贝来创建新的对象。LSP原则:所有的子类必须能够代替其父类的功能。6.2 集合类型Programming to Interfaces有哪些手段?l 迭代模式(主要用于集合)定义:提供一种方法顺序访问一个聚合对象的各个元素,而不暴露其内部表示*支持对集合对象的多种遍历方式;*支持对不同的集合对象统一遍历(多态迭代)效果:遵循设计规则,面向接口编程和信息隐藏 支持遍历一个集合的变化 迭
13、代简化了一个集合的接口和实现,也让责任各得其所 对一个集合有多种遍历方法两种方式: 外部迭代控制,按照客户的指示提供集合元素,客户控制元素的访问 内部迭代控制,内部控制的迭代机制接受操作,代表客户把他们应用于每个元素,迭代机制控制元素的访问,而不是由客户控制(更好)6.3 OCP的手段有哪些?【提示:不仅仅是继承】6.4 一个模块的信息隐藏有哪两种基本类型,各自有哪些典型的处理手段?l 每个隐藏一个重要的设计决策的实现细节,只有该模块的元素才知道该细节(看一下门面模式)l 隐藏改变,对于预期的改变,把可能改变从模块中分离开来,安排到新的类,方法或者设计单元中,使得这个可能改变的设计单元不会影响
14、其他部分(看一下策略、桥接、OCP、装饰、适配器模式)a) 门面模式(Faade Pattern):为模块或子系统提供一个或一系列统一的接口,定义高层的借口使得模块或子系统更加易于使用。信息隐藏:对客户端和一系列组件组成的子系统解耦。b) 策略模式(Strategy Pattern):将对象中的算法提取出来,作为一个对象封装。提高了可更改性和可重用性,但理解上复杂。c) 装饰模式(Decorator Pattern):不修改类的代码而扩展类的实例的功能。比静态的继承更加灵活。装饰器对接口来说是透明的。i. 特点1. 比静态集成更加灵活2. 避免类层次结构上的高负载3. 存在很多相似的小对象,很
15、难理解和调试4. 一个装饰器和它的组件并不唯一,识别对象可能产生问题d) 适配器模式(Adaptor Pattern):将已有类的接口转换为客户端期待的接口,是由于接口不统一的类能够共同工作。可以提高灵活性、重用性、鲁棒性。6.5 实现共性与可变性有哪些手段?对给定的场景,给出共性与可变性的设计方案。l 多态,父类共性,子类可变性l 聚合,Whole共性,Part可变性l 运行时注册,静态编译共性,运行时注册可变性(涉及到的模式:strategy,bridge,state,observer,command,具体是怎样实现共性差异性的没说,大家讨论理解一下)下面列出PPT上的相关内容: 策略模式
16、: 使用的情况: 许多相关类只在行为上不同,策略提供了一种用不同的行为配置类的方法 类定义了不同的行为,并且这些行为在操作上表现为不同的条件语句 需要不同的算法 算法使用的策略用户不应知道 Solution: 结果: 易修改性和可复用性、难于理解(用户必须知道所有策略然后再选择合适的) 注意:If there are complex and vary algorithms, then there may be Strategy PatternIf there is a changeable behavior in some fixed characteristics, then there m
17、ay be Strategy PatternIf there are complex conditional statements, then there may be Strategy Pattern 状态模式: 问题:对象的行为依赖于它的状态,在运行时根据状态改变 操作有多种选择结构对每个状态有多种选择(每个选择为一个类) 结构: 协作:Context委托给state具体的request,让它分配给现有的具体状态对象 Context可以把自己作为参数传递给ConcreteState对象 Context是用户的接触接口,用户无需和State接触 Context或者ContextState对象
18、可以决定ConcreteState对象的切换 结果: 状态具体行为本地化 状态转换明确 状态对象可以共享观察者模式 观察者模式定义了对象之间的一对多关系 主题用一个共同的接口来更新观察者 观察者和可观察者之间用松散耦合方式结合、可观察者不知道观察者的细节、只知道观察者实现了观察者的接口 类图 结果: 灵活性、可改变性、可重用性、更加复杂 使用观察者模式的情况1 当一个对象改变时,需要改变其他对象,而且不知道多少对象需要改变2 当对象需要notify其他的对象,而且不知道这些对象是什么 命令模式 问题根据表现的动作参数化对象在不同的时候specify, queue, and execute re
19、quests 通过存储上下文信息支持undo 为了恢复支持变更日志 类图 效果 将“动作的请求者”和“动作的执行者”解耦 可将command存放在Stack或者Queque中 可扩展性强,易于扩展Command 很容易支持undo和redod) 多态(继承)解决1对N关系:父对象对应共性,子对象对应差异性。e) 聚集关系,解决M对N关系:整体对应共性,部分对应差异性。f) 运行时注册:解决1对N或M对N关系:静态编译时确定对应共性,运行时体现的特性对应差异性。g) State Pattern:对象的行为依赖其状态。i. 优点0. 状态决定行为本地化1. 明确状态转换2. 状态对象能够被共享h)
20、 观察者模式(Observer Pattern):定义了对象之间一对多的依赖关系,当一个对象更改其状态,所有依赖它的对象都被通知,并且自动更新。增加了灵活性,可更改性,可重用性。但是更加复杂。i) 命令模式(Command Pattern):通常有Action可以指定,在不同的时间都可以执行请求,支持取消操作,为恢复支持更改日志i. 优点:0. 在发送和执行请求对象之间解耦1. 可以在队列或栈之中存储队列2. 很容易支持取消和redo3. 很容易扩展命令6.6 在解决De-Coupling时,常常使用哪些Indirection的手段?对给定的场景,给出Indirection的解决方案。6.7
21、De-Coupling有哪些手段?l 避免重复的代码,因为改变一个重复的代码,意味着要改变另一块l DIP,为一个模块定义一个接口,具体必须依赖于抽象l 继承,共性和变化l 设计模式 调停者模式 结构:参与者:Mediatorq 定义一个和Colleague对象交互的接口q 知道一些事件或者情况ConcreteMediator q 通过Colleagues间的协作实现合作q 知道并且维护他的ColleaguesColleague classesq 每个 Colleague 类知道他的Mediator对象q Colleagues之间的交互通过Mediatorq 给 mediator提供服务或者请
22、求q 有些请求对所有的Colleagues是通用的,也有各自不同的结果:定义了一个对象,它封装了一组对象间的交互通过使得对象间显示引用降低了耦合能够独立改变交互Lets you vary their interaction independently集中控制Centralizes control 桥接模式 将抽象的类层次和实现的类层次分离,使用委托(delegation)作为两者间的桥接 Abstraction 定义抽象接口 RefinedAbstraction 继承上面定义的抽象接口 Implementor 定义了实现类的接口;可以和Abstraction的接口不同。典型情况下,Implem
23、entor 提供了基本操作,Abstraction定义了基于这些基本操作定义高层操作 ConcreteImplementor 实现Implementor interface并且定义它的具体实现结果:将接口和实现解耦提高了可扩充性实现细节对Client隐藏j) 避免重复:Do it once。有重复意味着有耦合。k) 依赖倒置:为一个单独的模块定义接口是打破依赖,降低耦合的根本途径。l) 继承:可以将多个耦合降低为一个耦合。m) 设计模式:i. 调停者模式(Mediator Pattern): ii. 桥接模式:抽象和实现二者分离,适用于接口和实现都会发生修改的情况。 接口和实现部分解耦 提高了
24、可扩展性 对客户端隐藏了实现细节6.8 MVC与分层方式的区别【要具体到实现】6.9 对象的创建有哪些常见解决方法?【提示:这里要求常见解决方法,不是设计模式】a) 单键模式(Singleton Pattern):不是程序员来决定创建的次数而是由程序来决定。构造函数私有,只能自身调用;声明一个静态私有变量,指向自身;使用getinstance()代替构造函数创建实例。b) 工厂模式(Factory Pattern):适用于了解所有需要创建类型的情况c) Factory Method Pattern:为创建对象定义接口,但是让子类决定实例的类型。提高可修改性和可复用性,但增加了复杂度。d) 抽象
25、工厂模式(Abstract Factory):提供创建一系列相关或依赖对象的接口,通过这个接口不需要了解它们具体的类。iii. 优点0. 将具体类分离出来1. 是更改产品更加容易2. 各个产品之间的生产一致iv. 缺点0. 增加产品的类型很困难1. 需要重新对抽象工厂和其子类进行编写2. 在动态语言里表现不是很差e) 原型模式(Prototype Pattern):在创建类的过程中,实例化和初始化的过程十分复杂。优点:在运行时添加或删除原型,可以创建多种原型,伪动态加载。l 简单的对象创建 -Creator Pattern -Coupling Pattern -Cohesion Pattern
26、l 复杂对象的创建Scenario 1: only one instance permitted Singleton模式结构: Scenario 2: Limited instance permitted 在Singleton的基础上改进(看一下例子)A More complex scenario: type variations 工厂方法 定义了一个创建对象的接口,但由子类决定要实例的类是哪一个,让类把实例化推迟到子类 结构:参与者:Product (Document)*定义工厂方法创建的对象接口ConcreteProduct (MyDocument)* 实现产品接口Creator (App
27、lication)*声明工厂方法 *可能定义一个缺省的工厂方法实现,它返回一个缺省的ConcreteProduct对象ConcreteCreator (MyApplication)*重写工厂方法,返回实例ConcreteProduct 结果: 可改变性,可复用性,复杂 抽象工厂模式 提供一个接口,用于创建相关或者依赖对象的家族,而不需要明确具体的类 AbstractFactory声明了一个用于创建抽象产品的接口 ConcreteFactory实现了创建具体产品对象的操作:通常使用Singleton AbstractProduct为产品对象的类型声明一个接口,具体工厂生产这些产品 Concret
28、eProduct定义了被相关具体工厂创建的产品对象结果:good-分离了具体类;产品组更换更容易;保持产品组的一致bad-难支持新的产品种类;需要重新编码Abstract Factory和所有子类;但是在动态类型语言中不太差 Scenario 3: complex instantiation and initialization, such as:Runtime instantiation,Value varies in initialization 原型模式: 结果:运行时增删原型Specifying new objects by varying valuesq 加一个原型实际上新增了一个类
29、型Pseudo Dynamic loading7 设计模式部分所有的思考题a) 编程实现: Iterator Pattern and Proxy Patternb) 用Mediator Pattern 实现 CardShark游戏c) 实现前面Bridge Pattern的示例d) 利用Decorator解决下图的新增功能e) Adapt enumeration to iterator f) 如果一个对象集的一个行为需要协作对象来完成,但是它们在协作对象上存在差异性,如何处理?g) 如果一个对象集之间除共性外,有超过个的差异行为,如何处理? h) 如果一个对象集除了接口之外,全是差异行为,如何
30、处理? i) 从共性和差异性角度,如何解释Bridge模式? j) 比较strategy 与 statev. 1 of N or M of N?vi. Who control the changing?vii. How to change?0. Fixed rules or table-driven (configuration files)viii. Creating and destroying policy?k) “Context decide changing of ConcreteState object ”与“ ConcreteState decide changing of Co
31、ncreteState object”有何不同? l) Limited instance permitted,以singleton为基础,编写程序解决上述问题 m) 思考题,如果增加pizza类型t1,请基于Decorate模式完成对factory的修改n) 如果有多个其他类实例的创建类型都需要子类来决定怎么办? o) 如果多个其他类实例之间存在类型依赖该怎么办? (2) Open/Close PrincipleSoftware should be open for extension, but closed for modification.模块应该有secret:修改。对一个软件先预测它的修改,然后把修改独立出来,然后对其进行封装,如果change发生了,我们希望这个change易于扩展而不要进行修改。(3) MVC Pattern:a) 将核心业务模型与表现、控制逻辑使用功能划分开,允许多视图共享一个商业数据模型,使得支持多客户端更加易于实现、测试和维护。Strategy PatternObserver Pattern