软件构造week7

5-2(1) Subtyping
第一题
Behavioral subtyping必须要满足的条件,不包括
子类型override父类型的某方法,子类型方法需具备相同或更弱的post-condition
子类型必须要具备与父类型相同或更弱的invariants(不变量)
包括
子类型可以增加父类型中所没有的新方法
子类型override父类型的某个方法,不能比父类型方法抛出新的异常类型,但可比父类型方法抛出的异常更少

第二题
关于Behavioral subtyping的说法,正确的是
子类型override父类型某个方法,其返回值类型应该与父类型方法的返回值类型相同或者更具体(子类型)
不正确
子类型override父类型某个方法,其参数的类型应该与父类型方法的参数类型相同或者更具体
某个类是immutable的,它可以派生出一-个mutable的子类
java允许你这么设计, statictype checking也可以通过,但却是违反LSP的,因为immutable也是invariant (不变量),子类型的invariant应该等于或强于父类型,而一个mutable的子类型就不再具备这个invariant。
子类型override父类型某个public方法,子类型中该方法的可见性可以为private
把一个public方法override为private方法,那么如果用子类型的对象取代父类型对象,就无法调用这个操作了,所以无法取代,所以违反LSP。

第三题
public class A {
public object a (String d) {
return “”;}}
public class B extends A {
@Override
public String a (Object d) {
return null;}
}
该段Java代码是否能通过static type checking?
不能
解析:
虽然方法a在类A和类B里符合covariance和contra-variance ,但因为Java不支持contra-variance ,这里的@Override是不能成立的。

第四题
public class A {
public object a (String d) {
return “” ;}}
public class B extends A {
public String a (0bject d) {
return null;}}
该段Java代码是否能通过static type checking?

解析:方法a在类A和类B里符合covariance和contra-variance,但因为java不支持contra-variance,于是编译器就把B中的a方法看做A中a方法的overload

第五题
void print(List list){…}
以下作为参数传递进去不是对它的合法调用?
List a;
List<?> a;
Arraylist a;
List<? extends Object> a;
合法
List a;

第六题
void print(List<? extends Number> list){…}
以下作为参数传递进去是对它的合法调用?
List a;
ArrayList a;
List<? extends Integer> a;
不合法
List<?> a;
List<0bject> a;

5-2(2) 组合与委派、框架复用
第一题
关于delegation的说法,正确的
某些功能不需要ADT自己来做,而是委托其他ADT来做(调用其他ADT的方法)
在类1的构造器里传入类2的对B 象,即可在类1里使用传入的对象调用类2的操作
Delegation发生在object层面而非class层面
不正确的
为实现类1对类2的delegation,需要将类2作为类1的rep的一部分(即类2是类1的field)
不必需。可以动态传入类2的对象,然后调用其方法即可。
class A {
void a(B b) {
b.add()
}
}
在上面的代码中,B并未作为A的rep的一部分,只是在方法a中动态传入,然后调用b的add()方法。

第二题
关于Inheritance和delegation的说法,正确的
如果类1需要使用类2的大部分乃至全部方法,则最好将类1设计为类2的子类
如果类1只需使用类2的小部分方法,则最好通过delegation实现对类2的方法调用
Delegation发生在object层面,而inheritance发生在class层面
不正确的
用A has a B或A usea B表示A和B之间的inheritance关系,用A isa B表示_者之间的delegation关系
反了

第三题
关于Composite over inheritance原则,以下正确的是
若用继承,子类不得不继承父类的全部方法,但子类可能并不需要这么多方法
子类的不同对象可能具备不同的行为,若用继承实现,则不得不定义大量具有不同行为的子类,麻烦
若用继承,子类和父类之间的关系在编译阶段即硬性绑定,难以在运行时动态改变
若用delegation,可隔离两个类之间的静态绑定关系,从而支持运行时实例之间关系的动态改变

第四题
若事物o既有A行为(例如"飞”) ,也有B行为(例如“叫”),但具体如何实现这些行为可能会变化。那么ready for change的Java 0OP设计是
为A和B分别定义一个接口,各B) 自分别定义自己的方法;为o设计类,将其具体行为delegate到A和B的具体实现类将两类行为分别放在不同接口里, o的类通过delegation调用两类接口的具体实现。这是CRP原理的恰当应用。
不正确
定义一个接口,在其中为A和B分别定义- -组方法,然后为o设计一个类,实现该接口
如果o将来不再具备A或B的行为,那么需要修改该接口,会造成大量:依赖该接C的类随之修改。
为o设计类,在类中添加A和B的行为作为其一组方法
对接口编程,而非对类编程。
针对A设计一个类,针对B设计另一个类,然后让o的类同时继承A和B的类。
Java不支持多重继承。

第五题
Lab2的P3按照上述UML图进行设计,那么GoGame类的place( )方法(落子)的spec应该为
void place(GoAction a, …)
不正确
void place(Action a, …)
void place(…)
void place()
… 表示其他参数

第六题
Lab2的P3按照上述UML图进行设计,这么设计的优点是
客户端只需了解Game接口,无需获知其他任何信息
可容易的扩展其他棋类游戏(只需为Game和Action两个接口添加新的实现类)
如果要扩展支持真实的围棋规则,只需改GoAction类即可,最小化改变范围

第七题
关于黑盒与白盒framework的说法,正确的
白盒框架里实现了若干方法,用户程序通过override这些方法即可改变框架的行为
在黑盒框架里,用户编写类来实现框架提供的接口,框架运行时动态调用用户写的类中的方法
白盒框架的基本原理是inheritance,黑盒框架的基本原理是delegation
不正确的
黑盒框架运行时的主程序是用户写的类,白盒框架的主程序是框架本身的类

第八题
上图中表示delegation关系的是
c和e
a和d,并非ADT之间的关系:这里的 “终端用户”就是使用软件的真人了。

第九题
上图中表示继承或实现关系的是
c和e
c是用户开发的具体类实现了Plugin接 口,e是用户定义的类继承了 framework所提供的抽象类。

5-3 面向复用的设计模式
第一题
关于Adapter模式的说法,不正确的是
Adapter类可提供被复用的方法,但与Client要求的spec不吻合
Adaptee类用于将client的请求转化为对Adapter类的方法的调用
Adapter和ITarget之间的关系是inheritance
正确的
Adapter类和Adaptee类之间的关系是delegation

第二题
Adapter模式カ何要设计ITarget接口,而不是由client直接靖求Adapter的Request( )方法?
Client对接口编程,无需了解Adapter类
Adapter类可能友生変化,接口隔寓了変化,不会影响client代码
不正确的
Adaptee类可能友生変化,需要隔离client与它的变化
Client无法直接杓造Adapter的实例,故需要増加接口

第三题
关于Decorator设计模式的说法,正确的是
注:在以下选项中,A代表装饰之前的类,B代表装饰之后的类
A和B二者具有共同的祖先类或实现共同的接口
B中有一个成员变量,其类型为A
B中的某些方法中,通过delegation调用A的同名方法,并可扩展其他新功能
不正确
B中不可以增加A中所没有的方法

第四题
Stack t = new SecureStack (new SynchronizedStack (newUndoStack(s));
针对Decorator设计模式上述形式的client代码,以下说法不正确的是
第三行的s的类型是B UndoStack
第一行的t和第三行的s,其实是指向内存中同一个对象的两个不同alias
正确的
第三行的s的类型是Stack或其子类型
第一行的t的运行时类型是SecureStack

第五题
针对Facade设计模式,以下说法正确的
针对一个或多个已有的类,client需要调用它们的多个方法,故该模式将这些调用统一封装为一 个方法对外提供
该模式降低了client端使用已有类的代价,减少了client与已有类之间的耦合度
该模式所构造的封装类中的方法一般用static类型
不正确的
虽然减少了耦合度,该模式仍然需要client端显式构造出被封装类的实例

第六题
上图Strategy模式, 说法正确的是
ShoppingCart将pay( )的职责delegate给了PaymentStrategy
PaymentStrategy是接口,client的pay实际执行的是其某个实现类的pay()
若要扩展新的pay( )策略,只需为PaymentStrategy增加新的实现类
不正确的
Client端不需要了解PaymentStrategy的任何实现类即可使用其pay()
client必须要知道自己希望 使用的是哪个pay策略,然后构造其对 象,传入pay(PaymentStrategy p)方法, 才能调用p的pay()方法。

第七题
上图显示的Template模式,不正确的是
上图中的0rderProcessTemplate是"模板”,可以是接口,也可以是抽象类
Client可以更改对一系列doXXX( )方法的调用次序
正确的
ProcessOrder()是模板方法,包含了对一系列操作的调用
如果OrderProcessTemplate中没有某个doXXX( )方法的实现,则在NetOrder和StoreOrder中必须要实现它。

第八题
关于Iterator模式,不正确的是
为了让你的类A具备iteration的能力,需要A实现Iterator接口
为了让你的类A具备iteration的能力,还需要构造一个实现Iterable接口的类作为符合A特定需求的迭代器
正确的
Java里Iterable接口只有一个方法iterator(),它返回一个迭代器对象
Java里Iterator接口有三个方法hasNext(),next(),remove( )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值