当前位置:文档之家› 程序设计模式

程序设计模式

类之间的关系有几种?请列举
关联关系 双向关联 单向关联 自关联 重数性关联 聚合关系 组合关系 依赖关系 泛化关系 接口与实现关系



重数性关联关系的定义?
接口之间也可以有与类之间关系类似的继承关系和依赖关系,但是接口和类之间还存在一种实现关系(Realization),在这种关系中,类实现了接口,类中的操作实现了接口中所声明的操作。

解释 0..* ,0..1,m..n,1..1,1..*?
1..1 表示另一个类的一个对象只与一个该类对象有关系
0..* 表示另一个类的一个对象与零个或多个该类对象有关系
1..* 表示另一个类的一个对象与一个或多个该类对象有关系
0..1 表示另一个类的一个对象没有或只与一个该类对象有关系
m..n 表示另一个类的一个对象与最少m、最多n个该类对象有关系 (m<=n)

顺序图中,消息的 种类?
在顺序图中,有的消息对应于激活,表示它将会激活一个对象,这种消息称为调用消息(Call Message);如果消息没有对应激活框,表示它不是一个调用消息,不会引发其他对象的活动,这种消息称为发送消息(Send Message);如果对象的一个方法调用了自己的另一个方法时,消息是由对象发送给自身,这种消息称为自身消息(Self Call Message)。


解释大三律(Rule of Three)?
大三律(Rule of Three)
只有经过3个以上不同类型(或不同领域)的系统的校验,一个解决方案才能从候选模式升格为模式


解释设计模式(Design Pattern)?
设计模式(Design Pattern)
一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结
是一种用于对软件系统中不断重现的设计问题的解决方案进行文档化的技术
是一种共享专家设计经验的技术
目的:为了可重用代码、让代码更容易被他人理解、提高代码可靠性


设计模式:根据目的(模式是用来做什么的)可分为?根据范围,即模式主要是处理类之间的关系还是处理对象之间的关系,可分为?
根据目的(模式是用来做什么的)可分为创建型(Creational),结构型(Structural)和行为型(Behavioral)三类:
创建型模式主要用于创建对象
结构型模式主要用于处理类或对象的组合
行为型模式主要用于描述类或对象如何交互和怎样分配职责


根据范围,即模式主要是处理类之间的关系还是处理对象之间的关系,可分为类模式和对象模式两种:
类模式处理类和子类之间的关系,这些关系通过继承建立,在编译时刻就被确定下来,是一种静态关系
对象模式处理对象间的关系,这些关系在运行时变化,更具动态性




设计模式的优点?
设计模式的优点
融合了众多专家的经验,并以一种标准的

形式供广大开发人员所用
提供了一套通用的设计词汇和一种通用的语言,以方便开发人员之间进行沟通和交流,使得设计方案更加通俗易懂
让人们可以更加简单方便地复用成功的设计和体系结构
使得设计方案更加灵活,且易于修改
将提高软件系统的开发效率和软件质量,且在一定程度上节约设计成本
有助于初学者更深入地理解面向对象思想,方便阅读和学习现有类库与其他系统中的源代码,还可以提高软件的设计水平和代码质量



构造注入?
在实现依赖倒转原则时,我们需要针对抽象层编程,而将具体类的对象通过依赖注入(DependencyInjection, DI)的方式注入到其他对象中,依赖注入是指当一个对象要与其他对象发生依赖关系时,通过抽象来注入所依赖的对象。常用的注入方式有三种,分别是:构造注入,设值注入(Setter注入)和接口注入

构造注入:通过构造函数来传入具体类的对象

设值注入:通过Setter方法来传入具体类的对象

接口注入:通过在接口中声明的业务方法来传入具体类的对象


不要和“陌生人”说话 (Don't talk to strangers.),怎么理解?
迪米特法则:每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。

迪米特法则分析
不要和“陌生人”说话 (Don't talk to strangers.)
只与你的直接朋友通信 (Talk only to your immediate friends.)
(1) 当前对象本身(this)
(2) 以参数形式传入到当前对象方法中的对象
(3) 当前对象的成员对象
(4) 如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友
(5) 当前对象所创建的对象
任何一个对象,如果满足上面的条件之一,就是当前对象的“朋友”,否则就是“陌生人”
在应用迪米特法则时,一个对象只能与直接朋友发生交互,不要和“陌生人”发生直接交互,这样做可以降低系统的耦合度,一个对象的改变不会给太多其他对象带来影响




什么是缺省适配器模式(Default Adapter Pattern)?
缺省适配器模式(Default Adapter Pattern):当不需要实现一个接口所提供的所有方法时,可先设计一个抽象类实现该接口,并为接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可以选择性地覆盖父类的某些方法来实现需求,它适用于不想使用一个接口中的所有方法的情况,又称为单接口适配器模式



适配器模式优点、缺点和使用环境
适配器模式优点、缺点和使用环境?
模式优点
将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构增加了类的透明性和复用性,提

高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用灵活性和扩展性非常好类适配器模式:置换一些适配者的方法很方便对象适配器模式:可以把多个不同的适配者适配到同一个目标,还可以适配一个适配者的子类

模式缺点
类适配器模式:(1) 一次最多只能适配一个适配者类,不能同时适配多个适配者;(2) 适配者类不能为最终类;(3) 目标抽象类只能为接口,不能为类对象适配器模式:在适配器中置换适配者类的某些方法比较麻烦

模式适用环境
系统需要使用一些现有的类,而这些类的接口不符合系统的需要,甚至没有这些类的源代码
创建一个可以重复使用的类,用于和一些彼此之间没有太大关联的类,包括一些可能在将来引进的类一起工作




在对象适配器中,一个适配器能否适配多个适配者?如果能,应该如何实现?如果不能,请说明原因?如果是类适配器呢?
一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。

类适配器一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口




在什么情况下可以使用外观模式?
在什么情况下可以使用外观模式?
当要为一个复杂子系统提供一个简单接口时可以使用外观模式。该接口可以满足大多数用户的需求,而且用户也可以越过外观类直接访问子系统。
客户程序与多个子系统之间存在很大的依赖性。引入外观类将子系统与客户以及其他子系统解耦,可以提高子系统的独立性和可移植性。
在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度


外观模式与迪米特法则的关系?
外观模式又称为门面模式,它是一种对象结构型模式。外观模式是迪米特法则的一种具体实现,通过引入一个新的外观角色可以降低原有系统的复杂度,同时降低客户类与子系统的耦合度



解释外观模式(Facade Pattern)?
外观模式(Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式



在软件开发中如何将多个变化维度分离?
桥接模式。



如果系统中存在两个以上的变化维度,是否可以使用桥接模式进行处

理?如果可以,系统该如何设计?
可以 使用两次 桥接模式


如何一致地对待容器对象和叶子对象?
使用组合模式,组合模式通过一种巧妙的设计方案使得用户可以一致性地处理整个树形结构或者树形结构的一部分,它描述了如何将容器对象和叶子对象进行递归组合,使得用户在使用时无须对它们进行区分,可以一致地对待容器对象和叶子对象。


在组合模式的结构图中,如果聚合关联关系不是从Composite到Component的,而是从Composite到Leaf,如下图所示,会产生怎样的结果?
组合模式的关键是定义了一个抽象构件类,它既可以代表叶子,又可以代表容器,而客户端针对该抽象构件类进行编程,无须知道它到底表示的是叶子还是容器,可以对其进行统一处理。同时容器对象与抽象构件类之间还建立一个聚合关联关系,在容器对象中既可以包含叶子,也可以包含容器,以此实现递归组合,形成一个树形结构。如果不使用组合模式,客户端代码将过多地依赖于容器对象复杂的内部实现结构,容器对象内部实现结构的变化将引起客户代码的频繁变化,带来了代码维护复杂、可扩展性差等弊端。感觉不影响结果


解释组合模式?
组合模式:组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象


装饰模式的优缺点与适用环境?
模式优点
对于扩展一个对象的功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类,从而实现不同的行为可以对一个对象进行多次装饰具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,且原有类库代码无须改变,符合开闭原则。
模式缺点
使用装饰模式进行系统设计时将产生很多小对象,大量小对象的产生势必会占用更多的系统资源,在一定程度上影响程序的性能比继承更加易于出错,排错也更困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐
模式适用环境
在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时可以使用装饰模式


请用装饰模式设计变形金刚。

变形金刚在变形之前是一辆汽车,它可以在陆地上移动。当它变成机器人之后除了能够在陆地上移动之外,还可以说话;如果需要,它还可以变成飞机,除了在陆地上移动还可以在天空中飞翔。




透明装饰模式能否实现对同一个对象的多次装饰?为什么?
不能,因为半透明装饰模式是用具体装饰类型来定义装饰之后的对象,是确定的



如果一个软件系统在运行时所创建的相同或相似对象数量太多,将导致运行代价过高,带来系统资源浪费、性能下降等问题,如何避免系统中出现大量相同或相似的对象,同时又不影响客户端程序通过面向对象的方式对这些对象进行操作呢
享元模式


享元模式缺点是什么?
使得系统变得复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化
为了使对象可以共享,享元模式需要将享元对象的部分状态外部化,而读取外部状态将使得运行时间变长


几种常见的代理模式有哪几种?并解释。
远程代理(Remote Proxy):为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以在同一台主机中,也可以在另一台主机中,远程代理又称为大使(Ambassador)
虚拟代理(Virtual Proxy):如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建
保护代理(Protect Proxy):控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限
缓冲代理(Cache Proxy):为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果
智能引用代理(Smart Reference Proxy):当一个对象被引用时,提供一些额外的操作,例如将对象被调用的次数记录下来等


简述远程代理、虚拟代理、缓冲代理、保护代理的优点?
远程代理:可以将一些消耗资源较多的对象和操作移至性能更好的计算机上,提高了系统的整体运行效率
虚拟代理:通过一个消耗资源较少的对象来代表一个消耗资源较多的对象,可以在一定程度上节省系统的运行开销
缓冲代理:为某一个操作的结果提供临时的缓存存储空间,以便在后续使用中能够共享这些结果,优化系统性能,缩短执行时间
保护代理:可以控制对一个对象的访问权限,为不同用户提供不同级别的使用权限



代理模式适用环境?
当客户端对象需要访问远程主机中的对象时可以使用远程代理
当需要用一个消耗资源较少的对象来代表一个消耗资源较多的对象,从而降低系统开销、缩短运行时间时可以使用虚拟代理
当需要为某一个被频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享访问这些结果时可以使用缓冲代理
当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时可以使用保护代理
当需要为一个对象的访问(引用)提

供一些额外的操作时可以使用智能引用代理



命令模式的定义:命令模式:将一个请求封装为一个对象,从而让你可以用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作



策略模式:定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法可以独立于使用它的客户变化




备忘录模式的优缺点与适用环境?
模式优点
提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤实现了对信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动
模式缺点
资源消耗过大,如果需要保存的原发器类的成员变量太多,就不可避免地需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源
模式适用环境
保存一个对象在某一个时刻的全部状态或部分状态,这样以后需要时能够恢复到先前的状态,实现撤销操作防止外界对象破坏一个对象历史状态的封装性,避免将对象历史状态的实现细节暴露给外界对象




观察者模式的定义?
观察者模式:定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都得到通知并被自动更新。



观察者模式的优缺点与适用环境?
模式优点
可以实现表示层和数据逻辑层的分离
在观察目标和观察者之间建立一个抽象的耦合
支持广播通信,简化了一对多系统设计的难度
符合开闭原则,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便
模式缺点
将所有的观察者都通知到会花费很多时间
如果存在循环依赖时可能导致系统崩溃
没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而只是知道观察目标发生了变化
模式适用环境
一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用
一个对象的改变将导致一个或多个其他对象发生改变,且并不知道具体有多少对象将发生改变,也不知道这些对象是谁
需要在系统中创建一个触发链



什么是好莱坞原则?
在模板方法模式中,子类不显式调用父类的方法,而是通过覆盖父类的方法来实现某些具体的业务逻辑,父类控制对子类的调用,这种机制被称为好莱坞原则(Hollywood Principle),好莱坞原则的定义为:“不要给我们打电话,我们会给你打电话(Don‘t call us, we’ll call you)”。
在模板方

法模式中,好莱坞原则体现在:子类不需要调用父类,而通过父类来调用子类,将某些步骤的实现写在子类中,由父类来控制整个过程。



钩子方法的怎么使用 ?
钩子方法的引入使得子类可以控制父类的行为。
最简单的钩子方法就是空方法,也可以在钩子方法中定义一个默认的实现,如果子类不覆盖钩子方法,则执行父类的默认实现代码。
比较复杂一点的钩子方法可以对其他方法进行约束,这种钩子方法通常返回一个boolean类型,即返回true或false,用来判断是否执行某一个基本方法





在模板方法模式中,钩子方法如何实现子类控制父类的行为?
public virtual void Display() { }
钩子方法中定义一个默认的实现,如果子类不覆盖钩子方法,则执行父类的默认实现代码。

另一种钩子方法可以实现对其他方法进行约束,这种钩子方法通常返回一个bool类型,即返回true或false,用来判断是否执行某一个基本方法



什么是双重分派机制?如何用代码实现
在处理过程中调用了两次参数是接口或基类型的方法,这两次调用传的是接口或基类型的具体实现类或子类,这样的话CLR会在运行时两次具体确认参数的具体类型,从而正确调用方法的重载(也就是因为可能会存在参数是基类或具体子类的两种方法重载)。CLR的每一次处理,可称为一次分派。





集合元素基类E,子类SubE1,SubE2

有集合基类C,子类SubC1,SubC2. 基类C有元素类型是E的集合类型属性Items,SubC1和SubC2重写了Items属性,使其元素类型分别为SubE1,SubE2。

定义Visitor基类D及子类,其名为F1的处理方法的参数类型都是E

C有一个遍历所有Items的方法F2,参数类型是D. 在遍历调用过程中,对每一个元素X,使用F1方法并把元素X传给此方法。

这样在实际调用时,由于实例的Visitor类的不同,则会导致CLR对F2在运行时具体的参数类型进行确定过程,这就是第一次分派,而在F2内部过程中,在调用F1时由于元素实例的类型不同,会导致CLR对F1在运行时具体的参数类型进行确定过程,这就是第二次分派。





解释 透明装饰模式 和 半透明(Semi-transparent)装饰模式?
透明(Transparent)装饰模式:要求客户端完全针对抽象编程,装饰模式的透明性要求客户端程序不应该将对象声明为具体构件类型或具体装饰类型,而应该全部声明为抽象构件类型
对于客户端而言,具体构件对象和具体装饰对象没有任何区别
半透明装饰模式
半透明(Semi-transparent)装饰模式:用具体装饰类型来定义装饰之后的对象,而具体构件使用抽象构件类型来定义
对于客户端而言,具体构件类型无须关

心,是透明的;但是具体装饰类型必须指定,这是不透明的




抽象工厂模式的优缺点与适用环境?
模式优点
隔离了具体类的生成,使得客户端并不需要知道什么被创建
当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象
增加新的产品族很方便,无须修改已有系统,符合开闭原则
模式缺点
增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了开闭原则
模式适用环境
一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节
系统中有多于一个的产品族,但每次只使用其中某一产品族
属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来
产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构


相关主题
文本预览
相关文档 最新文档