试题六(装饰器类型)
阅读下列说明和java代码,将应填入 (n) 处的字句写在答题纸的对应栏内。
【说明】
某发票(lnvoice)由抬头(Head)部分、正文部分和脚注(Foot)部分构成。现采用装饰(Decorator)模式实现打印发票的功能,得到如图6-1所示的类图。
【java代码】
class invoice{
public void printInvoice(){
System.out.println ( "This is the content of the invoice!");
}
}
class Decorator extends Invoice {
protected Invoice ticket;
public Decorator(lnvoice t){
ticket = t;
}
public void printInvoice(){
if(ticket != null)
(1)ticket.printInvoice() ;
}
}
class HeadDecorator extends Decorator{
public HeadDecorator(lnvoice t){
super(t);
}
public void printInvoice (){
Systent.out.println( "This is the header of the invoice! ");
(2) ticket.printInvoice();
}
}
class FootDecorator extends Decorator {
public FootDecorator(Invoice t){
super(t);
}
public void printlnvoice(){
( 3) ticket.printInvoice();
Systent.out.println( "This is the footnote of the invoice! ");
}
}
Class test {
public static void main(String[] args){
Invoice t =new Invioce();
Invoice ticket;
ticket= (4) new FootDecorator(new HeadDecorator(t));
ticket.printInvoice();
Systent.out.println(“------------------“);
ticket= (5) new FootDecorator(new HeadDecorator(new Decorator(null)));
ticket.printInvoice();
}
}
程序的输出结果为:
This is the header of the invoice!
This is the content of the invoice!
This is the footnote of the invoice!
----------------------------
This is the header of the invoice!
This is the footnote of the invoice!
试题六(装饰器)
某咖啡店售卖咖啡时,可以根据顾客的要求在其中加入各种配料,咖啡店会根据所加入的配料来计算费用。咖啡店所供应的咖啡及配料的种类和价格如下表所示。
试题六(生成器类型)
阅读下列说明和 Java 代码,将应填入 (n) 处的字句写在答题纸的对应栏内。
【说明】
某快餐厅主要制作并出售儿童套餐,一般包括主餐(各类比萨)、饮料和玩具,其餐品种类可能不同,但其制作过程相同。前台服务员(Waiter) 调度厨师制作套餐。现采用生成器 (Builder) 模式实现制作过程,得到如图 6-1 所示的类图。
【Java 代码】
class Pizza {
private String parts;
public void setParts(String parts) { this.parts = parts;}
public String toString() { return this.parts; }
}
abstract class PizzaBuilder {
protected Pizza pizza;
public Pizza getPizza() { return pizza; }
public void createNewPizza() { pizza = new Pizza(); }
public (1) ;
}
class HawaiianPizzaBuilder extends PizzaBuilder {
public void buildParts() { pizza.setParts("cross + mild +ham&pineapp1e”};
}
class SpicyPizzaBuilder extends PizzaBuilder {
public void buildParts() { pizza.setParts("pan baked + hot +pepperoni&salami"); }
}
class Waiter {
private PizzaBuilder pizzaBuilder;
public void setPizzaBuilder(PizzaBuilder pizzaBuilder) { /*
设置构建器*/
(2) ;
}
public Pizza getPizza(){ return pizzaBuilder.getPizza(); }
public void construct() { /*构建*/
pizzaBuilder.createNewPizza();
(3) ;
}
}
Class FastFoodOrdering {
public static viod mainSting[]args) {
Waiter waiter = new Waiter();
PizzaBuilder hawaiian_pizzabuilder = new
HawaiianPizzaBuilder();
(4) ;
(5) ;
System.out.println("pizza: " + waiter.getPizza());
}
}
程序的输出结果为:
Pizza:cross + mild + ham&pineapple
试题六(桥接模式)
阅读下列说明和Java代码,将应填入一且上一处的字句写在答题纸的对应栏内。
【说明】
某图像预览程序要求能够查看BMP 、JPEG和GIF三种格式的文件,且能够在Windows和Linux两种操作系统上运行。程序需具有较好的扩展性以支持新的文件格式和操作系统。为满足上述需求并减少所需生成的子类数目,现采用桥接模式进行设计,得到如图6-1所示的类图。
【问题1】
【Jave代码】
Import java.util.*;
class Matrix{ //各种格式的文件最终都被转化为像素矩阵
//此处代码省略
};
abstract class Implementor{
Public(1);//显示像素矩阵 m
};
class WinImp extends Implementor{
public void doPaint(Matrix m){ //调用 Windows 系统的绘制函数绘制像素矩阵
}
};
class LinuxImp extends Implementor{
public void doPaint(Matrix m){ //调用 Linux 系统的绘制函数绘制像素矩阵
}
};
abstract class Image{
public void setImp(Implementor imp){ this.imp= imp; }
public abstract void parseFile(String fileName);
protected Implementor imp;
};
class BMPImage extends Image{
//此处代码省略
};
class GIFImage extends Image{
public void parseFile(String fileName) {
//此处解析BMP文件并获得一个像素矩阵对象m
(2);//显示像素矩阵m
}
};
Class Main{
Public static viod main(String[]args){
//在Linux操作系统上查看demo.gif图像文件
Image image=(3)
Implementor imageImp=(4)
(5)
Image.parseFile(〝demo.gif〝);
}
}
1.abstract void doPaint(Matrix m)
2.imp.doPaint(m)
3.new GIFImage()
4.new LinuxImp()
5.image.setImp(imageImp)
试题六(策略类)
【说明】
某大型购物中心欲开发一套收银软件,要求其能够支持购物中心在不同时期推出的各种促销活动,如打折、返利(例如,满300返100)等等。现采用策略( Strategy)模式实现该要求,得到如图6-1所示的类图。
(1) double acceptCash(double money)
(2) cs=new CashNormal()
(3) cs=new CashReturn(300,100)
(4) cs=new CashDiscount(0.8)
(5) return cs.acceptCash(money)
试题六(组合模式)
阅读下列说明和Java代码,将应填入(n)处的字句写在答题纸的对应栏内- 【说明】
现欲构造一文件/目录树,采用组合(Composite)设计模式来设计,得到的类图如下图所示:
【问题1】
(1) abstract
(2) null
(3) List
(4) childList
(5) printTree(file)
试题六(组合模式)
某公司的组织结构图如图6-1所示,现采用组合(Composition)设计模式来设计,得到如图6-2所示的类图。
其中Company为抽象类,定义了在组织结构图上添加(Add)和删除(Delete)分公司/办事处或者部门的方法接口。类ConcreteCompany表示具体的分公司或者办事处,分公司或办事处下可以设置不同的部门。类HRDepartment和FinanceDepartment分别表示人力资源部和财务部。
【问题1】
试题六(组合模式)
某饭店在不同的时段提供多种不同的餐饮,其菜单的结构图如图6-1所示。
现在采用组合(Composition)模式来构造该饭店的菜单,使得饭店可以方便地在其中增加新的餐饮形式,得到如图6-2所示的类图。其中MenuComponent为抽象类,定义了添加(add)新菜单和打印饭店所有菜单信息(print)的方法接口。类Menu表示饭店提供的每种餐饮形式的菜单,如煎饼屋菜单、咖啡屋菜单等。每种菜单中都可以添加子菜单,例如图6-1中的甜点菜单。类Menultem表示菜单中的菜式。
【Java代码】
(1) abstract class 或 public abstract class
(2) public abstract void add(MenuComponent menuComponent)
或 abstract void add(MenuComponent menuComponent)
或 protected abstract void add(MenuComponent menuComponent) ,
(3) add(menuComponent)
(4) menuComponent.print()
(5) allMenus.print()
Composite模式将对象组合成树形结构以表示“整体-部分”的层次结构,其中的组合对象使得你可以组合基元对象以及其他的组合对象,从而形成任意复杂的结构。 Composite模式使得用户对单个对象和组合对象的使用具有一致性。
Composite模式的结构下图所示。
其中:
•类Component为组合中的对象声明接口,在适当的情况下,实现所有类共有接口的缺省行为,声明一个接口用于访问和管理Component的子部件:
•类Leaf在组合中表示叶节点对象,叶节点没有子节点;并在组合中定义图元对象的行为;
•类Composite定义有子部件的那些部件的行为,存储子部件,并在Component 接口中实现与子部件有关的操作;
•类Client通过Component接口操纵组合部件的对象。
下列情况可以使用Composite模式:
(1) 表示对象的整体-部分层次结构;
(2) 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
试题六将组合模式应用到饭店菜单的构造中。图6-2屮的类MenuComponent对应上图中的Component,Menultem对应Leaf,Menu对应Composite。在实现时,通常都会把Component定义为抽象类。
在Java中,用abstract关键字限定的类即为抽象类,所以(1)处应填入abstract class。
(2)处根据注释,这里应该定义功能为“添加新菜单”的成员函数。在子类Menultem和Menu中可以看到,都有add成员函数,说明子类中重置了父类中的成员函数。所以(2) 处应填入 public abstract void add(MenuComponent menuComponent)。
由图6-2可以看出,Menu中包含了MenuComponent的对象集合。程序中用Java中的list来实现这个聚集关系,这样就可以利用list中提供的各种方法了。list中用于添加元素的方法是add,所以(3)处应填入add(menuComponent)。
(4) 处出现在方法print中,其功能是打印出所有菜单的信息。这里使用了list中的迭代器类iterator,遍历每个子菜单,并调用子菜单中定义的print方法打印该子菜单的信息。(4)处应填入menuComponent.print()。
为了能够在main中打印出所有的菜单信息,必须使用表示菜单结构中最顶层菜单的对象来调用print,因此(5)处应填入allMenus.print()。
试题六(策略模式)
某软件公司现欲开发一款飞机飞行模拟系统,该系统主要模拟不同种类飞机的飞行特征与起飞特征。需要模拟的飞机种类及其特征如表6-1所示。
为支持将来模拟更多种类的飞机,釆用策略设计模式(Strategy)设计的类图如图6-1所示。
图6-1中,AirCraft为抽象类,描述了抽象的飞机,而类Helicopter、AirPlane、Fighter 和Harrier分别描述具体的飞机种类,方法fly()和takeOffQ分别表示不同飞机都具有飞行特征和起飞特征;类FlyBehavior与TakeOffBehavior为抽象类,分别用于表示抽象的飞行行为与起飞行为;类SubSonicFly与SuperSonicFly分别描述亚音速飞行和超音速飞行 的行为;类VerticalTakeOff与LongDistanceTakeOff分別描述垂直起飞与长距离起飞的 行为。
【问题1】
(1) FlyBehavior flyBehavior
(2) TakeOffBehavior takeOffBehavior
(3) flyBehavior.fly()
(4) takeOffBehavior.takeOff()
(5) extends
(6) SubSonicFly()
(7) VerticalTakeOff()
试题六(状态模式)
某大型商场内安装了多个简易的纸巾售卖机,自动出售2元钱一包的纸巾,且每次仅售出一包纸巾。纸巾售卖机的状态图如图6-1所示。
采用状态(State)模式来实现该纸巾售卖机,得到如图6-2所示的类图。其中类State为抽象类,定义了投币、退币、出纸巾等方法接口。类SoldState、SoldOutState、 NoQuarterState和HasQuarterState分别对应图6-1中纸巾售卖机的4种状态:售出纸巾、纸巾售完、没有投币、有2元钱。
【问题1】
(1)State
(2)tissueMachine.getHasQuarterStat()
(3)tissueMachine.getNoQuarterState()
(4)tissueMachine.getNoQuarterState()
(5)tissueMachine.getSoldOutState()
本题考查状态(State)模式的概念及应用。
状态模式是一种对象的行为型模式,允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。状态模式的类图如下所示:
状态模式主要解决的是控制一个对象转换的条件表达式过于复杂的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
题目利用状态模式来实现一个简易的纸巾售卖机。售卖机的状态转换图已经在题目中给出,类SoldState、SoldOutState、NoQuarterState 和 HasQuarterState 分别用来表示售卖机的4种不同状态,对应于状态模式中的ConcreteState1,...ConcreteStateN。题目所
设置的填空,主要集中在状态转换上。因此解答该题时,要求在理解状态模式内涵的基础上,依据纸巾售卖机的状态转换原则,给出正确的状态设置。
空(1)出现在类TissueMachine的数据成员定义部分。状态模式封装了状态的转换过程,但是它需要枚举可能的状态,因此需要实现确定状态种类。因此在类TissueMachine 中需定义出所有可能的状态对象。根据所给出的对象名称及说明中的描述,可知(1)处 应填入的类名为State。
空(2)〜(5)要求填写类TissueMachine中的方法setState在不同调用处的实际参数。这里的一个难点在于题目中没有显示地给出方法setState的原型及语义,这要求考生根据面向对象程序设计风格及说明中给出的应用场合来推断setState的内涵及原型,主要是确定其参数列表。
在面向对象程序设计中,为了做到封装,通常都会把数据成员定义为私有的。私有的数据成员对象不能直接访问,因此在类中都会提供2组访问私有数据成员的方法,分别为get...方法和set...方法(…代表对应的数据成员名称)。get...方法表示获取私有数据成员的值,其返回值类型为对应的数据成员的类型;set...方法表示对数据成员进行赋值,所要赋的值通常通过参数传递进去,方法的返回值类型通常为void。根据面向对象 程序设计的这些特点,以及状态模式的内涵及应用场合,可以推断出setState方法的功能就是设置纸巾售卖机的当前状态。纸巾售卖机在任一时刻只能处于一个唯一的状态, 由状态模式可知,纸巾售卖机的状态都是用状态对象表示的,由此就可以确定出,setState 方法的参数只要一个就可以了,就是表示纸巾售卖机下一状态的状态对象。
经过以上分析之后,可以明确空(2)〜(5)空所填的内容都应与状态转换相关。因此要填充这些空,只要对照图5-1的状态转换图,根据状态转换的条件确定出当前状态及下一状态即可。
空(2)出现在方法insertQuarter内,即给纸巾售卖机投入2元钱。根据状态图,“投入2元钱”之后,售卖机应转换到“有2元钱”的状态。“有2元钱”对应的状态的类为“HasQuarterState”,所以空(2)处应填写类HasQuarterState的对象。由此得出(2)应填 tissueMachine.getHasQuarterState()。
同理,空(3)表示的状态是从“有2元钱”状态,经历“退回2元钱”事件之后 的状态,及“没有投币”状态。所以空(3)处应填tissueMachine.getNoQuarterState()。
空(4)和(5)处分别表示卖出一包纸巾之后,售卖机应该转换到的下一个状态。 这个跟售卖机中的纸巾数有关,如果还有纸巾,则转换到“没有投币”状态,如果没有纸巾了,则转换到“纸巾售完”状态,因此,空(4)处应填tissueMachine.getNoQuarterState(),空(5)处应填tissueMachine.getSoldOutState()。