问题 问答题

试题六(共15分)阅读下列说明和Java代码,将应填入____(n)_____处的字句写在答题纸的对应栏内。[说明]某咖啡店售卖咖啡时,可以根据顾客的要求在其中加入各种配料,咖啡店会根据所加入的配料来计算费用。咖啡店所供应的咖啡及配料的种类和价格如下表所示。

答案

参考答案:(1) abstract(2) String getDescription(3) abstract int cost()(4) Beverage beverage(5) beverage(6) beverage

解析:本题考查装饰器(Decorator)模式的概念及应用。 Decorator模式动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式提供了比继承更有弹性的替代方案。 Decorator模式的优点是有效避免了使用继承方式扩展对象功能而带来的灵活性差、子类无限制扩展的问题;装饰者与被装饰者之间虽然都是同一类型,但是它们彼此是完全独立并可以独立任意改变的。 Decorator模式的适用场合是:想透明并且动态地给对象增加新的职责;给对象增加的职责,在未来存在增加或减少的可能。 Decorator模式的类图如下所示: 题目利用Decorator模式来计算各种配料组合的咖啡的价格。Beverage相当于抽象的Component类,最终要计算出Beverage的价钱。Espresso和DarkRoast是4个具体的组件,代表一种咖啡类型。M跳ha和Whlp是配料装饰者,可以添加到不同类型的咖啡中。CondimentDecorator相当于Decorator,是装饰者共同实现的接口。在本题中,确定装饰者共同实现的接口是什么,是一个重要的考查点。

下面来分析程序。 Decorator模式中的Component通常都用抽象类来实现。所以第(1)空应填写“abstract”。 第(2)、(3)空要求确定Beverage中提供的公共接口。解答时应全面阅读程序,通过于类的代码来推断父类所提供的接口是什么。 首先来观察Beverage的两个子类。在Espresso和DarkRoat中都出现的成员函数是cost,其功能是给出咖啡的价格:而在这两个类中,cost的实现代码又不相同。这意味着需要在这两个类的父类中定义一个抽象函数,其函数原型就应该是int cost()。现在回到第(2)、(3)空。第(2)空给出了成员函数的实现体,说明(2)处的成员函数是与description相关的。也就是说,第(2)空处的成员函数不可能是cost。这样就可以确定第(3)空应该是cost成员函数。所以第(3)空应填写“abstract int cost()”。 如何来确定第(2)空在类Espresso和DarkRoast中已经找不到相关信息了,我们考查剩余的类。 类CondimentDecorator是Beverage的子类,那么第(2)和(3)空处的成员函数都会被它继承。而类Mocha和则如又是CondimentDecorator的子类,第(2)和(3)空处的成员函数同样也会被这两个类继承。观察Mocha和Whip的代码,可以发现在这两个子类中也重置了抽象函数cost。除此之外还可以发现,在这两个子类中都出现了成员函数String getDescription()。从子类沿着继承路径追溯到父类,可以确定第(2)空就应该是成员函数getDescription最初的定义之处。所以第(2)空应填写“String getDescription”。 第(4)空考查的是类CondimentDecorator中定义的数据成员,要求确定其类型和名称。由于声明成了protected,因此在其子类Mocha和Whip中可以找到答案。在这两个类中都出现了“this.beverage”表达式,说明beverage应该是该类的数据成员。但在这两个类中都没有定义数据成员,很显然,这个数据成员应该是从父类继承而来的。所以第(4)空应填“Beverage beverage”。 第(5)和(6)空考查的是Decorator模式的使用方法。从主函数可知,其基本过程是现制作一杯烘焙咖啡(DarkRoast),然后再向这杯咖啡中加入1份Mocha和1份Whip,最后这杯咖啡的价格应该是烘焙咖啡的价格+1份Mocha的价格+1份Whip的价格。(5)和(6)处都应该填写“beverage”。

单项选择题
单项选择题