一. 单选题(共12题)

  1. (单选题)场景( )不是状态模式的实例。 A. 银行账户根据余额不同拥有不同的存取款操作 B. 游戏软件中根据虚拟角色级别的不同拥有不同的权限 C. 某软件在不同的操作系统中呈现不同的外观 D. 会员系统中会员等级不同可以实现不同的行为 我的答案: C:某软件在不同的操作系统中呈现不同的外观;正确答案: C:某软件在不同的操作系统中呈现不同的外观;

  1. (单选题)以下关于状态模式叙述错误的是( )。 A. 状态模式允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类 B. 状态模式中引入了一个抽象类来专门表示对象的状态,而具体的状态都继承了该类,并实现了不同状态的行为,包括各种状态之间的转换 C. 状态模式使得状态的变化更加清晰明了,也很容易创建对象的新状态 D.状态模式完全符合开闭原则,增加新的状态类无须对原有类库进行任何修改 我的答案: D:状态模式完全符合开闭原则,增加新的状态类无须对原有类库进行任何修改 ;正确答案: D:状态模式完全符合开闭原则,增加新的状态类无须对原有类库进行任何修改 ;

  1. (单选题)以下关于策略模式叙述错误的是( )。 A. 策略模式是对算法的包装,是把算法的责任和算法本身分隔开,委派给不同的对象管理 B. 在Context类中,维护了对各个ConcreteStrategy的引用实例,提供了一个接口供ConcreteStrategy存储数据 C. 策略模式让算法独立于使用它的客户而变化 D. 策略模式中,定义一系列算法,并将每一个算法封装起来,并让它们可以相互替换 我的答案: B:在Context类中,维护了对各个ConcreteStrategy的引用实例,提供了一个接口供ConcreteStrategy存储数据;正确答案: B:在Context类中,维护了对各个ConcreteStrategy的引用实例,提供了一个接口供ConcreteStrategy存储数据;

  1. (单选题)以下关于策略模式的优缺点描述错误的是( )。 A. 策略模式中,客户端无须知道所有的策略类,系统必须自行提供一个策略类 B. 策略模式可以避免使用多重条件转移语句 C. 策略模式会导致产生大量的策略类 D. 策略模式提供了管理相关算法族的办法 我的答案: A:策略模式中,客户端无须知道所有的策略类,系统必须自行提供一个策略类;正确答案: A:策略模式中,客户端无须知道所有的策略类,系统必须自行提供一个策略类;

  1. (单选题)某系统中用户可自行动态选择某种排序算法之一(如选择排序、冒泡排序、插入排序)来实现某功能,该系统的设计可以使用( )设计模式。 A. 状态 B. 策略 C.工厂方法 D. 模板方法 我的答案: B:策略;正确答案: B:策略;

  1. (单选题)某系统中的模板方法某子模块需要为其他模块提供访问不同数据库系统(Oracle、SQL Server、DB2 UDB 等)的功能,这些数据库系统提供的访问接口有一定的差异,但访问过程却都是相同的,例如,先连接数据库,再打开数据库,最后对数据进行查询,可使用( )设计模式抽象出相同的数据库访问过程。 A. 观察者 B. 访问者 C. 模板方法 D. 策略 我的答案: B:访问者;正确答案: C:模板方法;

  1. (单选题)以下关于模板方法模式的叙述错误的是( )。 A. 模板方法模式定义了一个操作中算法的骨架,而将一些步骤延迟到子类中 B. 模板方法模式是一种对象行为型模式 C. 模板方法使得子类可以不改变一个算法的结构即可重定义该算法某些特定步骤 D. 模板方法不仅可以调用原始的操作,还可以调用定义于AbstractClass中的方法或其他对象中的方法 我的答案: B:模板方法模式是一种对象行为型模式;正确答案: B:模板方法模式是一种对象行为型模式;

  1. (单选题)以下关于访问者模式的叙述错误的是( )。 A. 访问者模式表示一个作用于某对象结构中的各元素的操作 B. 访问者模式使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作 C. 在访问者模式中,ObjectStructure提供一个高层接口以允许访问者访问它的元素 D. 访问者模式使得增加新的元素变得很简单 我的答案: D:访问者模式使得增加新的元素变得很简单;正确答案: D:访问者模式使得增加新的元素变得很简单;

  1. (单选题)关于访问者模式中的对象结构,以下描述错误的是( )。 A. 它实现了accept()方法,该操作以一个具体访问者作为参数 B. 可以提供一个高层的接口以允许访问者访问它的元素 C. 可以是一个组合模式或是一个集合 D. 能够枚举其中包含的元素 我的答案: A:它实现了accept()方法,该操作以一个具体访问者作为参数;正确答案: A:它实现了accept()方法,该操作以一个具体访问者作为参数;

  1. (单选题) 在某飞行器模拟系统中,用户通过调节参数可以得到飞机的燃油消耗曲线和发动机燃烧效率曲线,用户可以向文本框输入参数值,也可以通过滑块来设置参数值,还可以通过下拉框来选择参数值,系统界面如下图所示,在该系统的设计中可以使用( )设计模式。 image.png A. 适配器或命令 B. 工厂方法或外观 C. 中介者或观察者 D. 策略或模板方法 我的答案: D:策略或模板方法;正确答案: C: 中介者或观察者 ;

  1. (单选题)在很多流行的交互式绘图程序中,当用户选择不同的绘图工具时图形编辑器的行为将随当前工具的变化而改变。如当一个“绘制椭圆”工具被激活时,可以创建椭圆对象;当一个“选择”工具被激活时,可以选择图形对象;当一个“填充”工具被激活时,可以给图形填充颜色等。在该程序中,可以使用( )设计模式来根据当前的工具来改变编辑器的行为。 A. 工厂方法 (Factory Method)
    B. 状态 (State) C. 备忘录 (Memento)
    D. 访问者 (Visitor) 我的答案: A:工厂方法 (Factory Method) ;正确答案: B:状态 (State);

  1. (单选题) 在Java异常处理中经常存在与下述代码片段类似的代码:
try {
    ……
}

catch(ArithmeticException are) {
    System.out.println("算术错误!");
}

catch(ClassNotFoundException e1) {
    System.out.println("类没有找到!");
}

catch(SQLException e2) {
    System.out.println("数据库操作错误!");
}

分析上述代码,在Java异常处理机制中蕴含了( )设计模式。 A. 命令 (Command)
B. 观察者 (Observer) C. 迭代器 (Iterator)
D. 职责链 (Chain of Responsibility) 我的答案: A:命令 (Command) ;正确答案: D


二. 填空题(共2题)

  1. (填空题)某软件公司现欲开发一款飞机模拟系统,该系统主要模拟不同种类飞机的飞行特征与起飞特征。需要模拟的飞机种类及其特征如表1所示。 image.png 为支持将来模拟更多种类的飞机,采用策略设计模式(Strategy)设计的类图如图所示。 image.png 图中,AirCraft为抽象类,描述了抽象的飞机,而类Helicopter、AirPlane、Fighter和Harrier分别描述具体的飞机种类,方法fly()和takeOff()分别表示不同飞机都具有飞行特征和起飞特征;类FlyBehavior与TakeOffBehavior为抽象类,分别用于表示抽象的飞行行为与起飞行为;类SubSonicFly与SuperSonicFly分别描述亚音速飞行和超音速飞行的行为;类VerticalTakeOff与LongDistanceTakeOff分别描述垂直起飞与长距离起飞的行为。
【Java代码】
interface FlyBehavior{
    public void fly();
}

class SubSonicFly implements FlyBehavior{
    public void fly() {System.out.println("亚音速飞行!");}
}

class SuperSonicFly implements FlyBehavior{
    public void fly() {System.out.println("超音速飞行!");}
}

interface TakeOffBehavior{
    public void takeOff();
}

class VerticalTakeOff implements TakeOffBehavior{
    public void takeOff() {System.out.println("垂直起飞!");}
}

class LongDistanceTakeOff implements TakeOffBehavior{
    public void takeOff() {System.out.println("长距离起飞!");}
}

abstract class AirCraft{
    protected     (1)    ;
    protected     (2)    ;
    public void fly() {     (3)    ; }
    public void takeOff() {     (4)    ; }
}

class Helicopter     (5)     AirCraft {
    public Helicopter() {
       flyBehavior = new     (6)    ;
       takeOffBehavior = new     (7)    ;   
    }
}

//其他代码省略

正确答案: (1) FlyBehavior flyBehavior (2) TakeOffBehavior takeOffBehavior (3) flyBehavior.fly() (4) takeOffBehavior.takeOff() (5) extends (6) SubSonicFly() (7) VerticalTakeOff()


  1. (填空题)某图书管理系统中,需要处理每一个书库中资料的页数和作者等信息。书库中的资料包括图书、期刊和论文,其中有些论文是独立存在的,有些论文作为期刊的一部分。使用访问者模式设计该系统,类图如图1所示: image.png 在图1中,ItemHandler是抽象访问者,声明了访问不同类型元素的方法,PageHandler和AuthorHandler作为具体访问者,分别用于对页数和作者信息进行处理;Item是抽象元素类,其子类Book表示图书、Magazine表示期刊、Paper表示论文;Library充当对象结构,用于存储图书、期刊和论文等资料信息。
【Java代码】

import java.util.*;
abstract class ItemHandler
{
 public abstract void handle(Book item);
 public abstract void handle(Magazine item);
 public abstract void handle(Paper item);
}

class PageHandler extends ItemHandler
{
 public void handle(Book item)
 {  //图书页数处理
 System.out.println("图书:《" + item.bookName +  "》页数:" + item.totalPages);  
 }
 public void handle(Magazine item)
 {  //期刊页数处理
 int pages = 0;
    for(Object obj : item.papers)
    {
    pages =           (1)          ;  //计算期刊总页数
    }
 System.out.println("杂志:《" + item.magazineName + item.magazineNo +  "》页数:" + pages);  
 System.out.println("  包含论文如下:");
 for(Object obj : item.papers)
    {
    System.out.println("      论文:《" + ((Paper)obj).paperTitle +  "》页数:" + ((Paper)obj).pages);
    }
 }

 public void handle(Paper item)
 {  //论文页数处理 
 System.out.println("论文:《" + item.paperTitle +  "》页数:" + item.pages);  
 }

}



class AuthorHandler extends ItemHandler
{

 public void handle(Book item)
 {  //图书作者处理,代码省略  }

 public void handle(Magazine item)
 {  //期刊作者处理,代码省略  }

 public void handle(Paper item)
 {  //论文页数处理,代码省略  }
}



interface Item
{
 public void accept(ItemHandler handler);
}



class Magazine implements Item
{
 public List papers = new ArrayList();
 public String magazineName;
 public String magazineNo;
 public void addPaper(Paper paper)
 {
         (2)        ;
 }

 public void accept(ItemHandler handler)
 {
         (3)        ;
 }
}


class Book implements Item
{
 public String bookName;
 public String author;
 public int totalPages;
 public void accept(ItemHandler handler)
 {
                                  (4)        ;
 }
}


class Paper implements Item
{
 public String paperTitle;
 public String author;
 public int pages;
 public void accept(ItemHandler handler)
 {
         (5)        ;
 }
}

class Libaray
{
 private List items = new ArrayList();
 public void addItem(Item item)
 {
           (6)          ;
 }
 public void accept(ItemHandler handler)
 {
 for(Object obj : items)
 {
             (7)            ;
 }
 }
}

class Test
{
 public static void main(String args[])
 {
 Book book = new Book();
 book.bookName = "21天精通九阳神功";
 book.author = "张无忌";
 book.totalPages = 450;
 Magazine magazine = new Magazine();
 magazine.magazineName = "功夫学报";
 magazine.magazineNo = "2011年第1期";
 Paper paper1 = new Paper();
 paper1.paperTitle = "如何单手制服敌人";
 paper1.author = "杨过";
 paper1.pages = 12;
 Paper paper2 = new Paper();
 paper2.paperTitle = "我和杨过的功夫情缘";
 paper2.author = "小龙女";
 paper2.pages = 8;
 Paper paper3 = new Paper();
 paper3.paperTitle = "研究报告-靖哥哥的九大弱点";
 paper3.author = "黄蓉";
 paper3.pages = 30;
 magazine.addPaper(paper1);
 magazine.addPaper(paper2);

 Libaray lib = new Libaray();
 lib.addItem(book);
 lib.addItem(magazine);
 lib.addItem(paper3);
 ItemHandler handler = new PageHandler();
         (8)        ;   //访问对象结构
 }
}

正确答案: (1) pages + ((Paper)obj).pages (2) papers.add(paper) (3) handler.handle(this) (4) handler.handle(this) (5) handler.handle(this) (6) items.add(item) (7) ((Item)obj).accept(handler) (8) lib.accept(handler)


三. 判断题(共3题)

  1. (判断题)访问者模式对“开闭原则”的支持具有倾斜性。增加新的访问者很方便,但是增加新的元素很困难。 A. 对 B. 错 我的答案: 对正确答案: 对

  1. (判断题)策略模式的环境类中可以包含多个不同抽象策略类的引用。 A. 对 B. 错 我的答案: 对正确答案: 对

  1. (判断题)模板方法模式中的基本方法也可以是钩子方法。 A. 对 B. 错 我的答案: 对正确答案: 对

四. 简答题(共1题)

  1. (简答题)某公司OA系统中包含一个员工信息管理子系统,该公司员工包括正式员工和临时工,每周人力资源部和财务部等部门需要对员工数据进行汇总,汇总数据包括员工工作时间、员工工资等。该公司基本制度如下: (1) 正式员工每周工作时间为40小时,不同级别、不同部门的员工每周基本工资不同;如果超过40小时,超出部分按照100元/小时作为加班费;如果少于40小时,所缺时间按照请假处理,请假所扣工资以80元/小时计算,直到基本工资扣除到零为止。除了记录实际工作时间外,人力资源部需记录加班时长或请假时长,作为员工平时表现的一项依据。 (2) 临时工每周工作时间不固定,基本工资按小时计算,不同岗位的临时工小时工资不同。人力资源部只需记录实际工作时间。

现使用访问者模式设计该系统。

1、画出UML类图

image.png

2、使用Java语言编程实现

public class Client {

   public static void main(String[] args) {

       EmployeeList list = new EmployeeList();

       Employee fte1 = new FullTimeEmployee("正式员工1", 12200.00, 45);
       list.addEmployee(fte1);
       Employee fte2 = new FullTimeEmployee("正式员工2", 16000.00, 40);
       list.addEmployee(fte2);
       Employee fte3 = new FullTimeEmployee("正式员工3", 9400.00, 38);
       list.addEmployee(fte3);

       Employee pte1 = new PartTimeEmployee("临时工1", 180.00, 20);
       list.addEmployee(pte1);
       Employee pte2 = new PartTimeEmployee("临时工2", 110.00, 60);
       list.addEmployee(pte2);

       Department dep = (Department) XMLUtil.getBean();
       list.accept(dep);
   }
}



import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XMLUtil {
   public static Object getBean() {
       try {
           DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
           DocumentBuilder builder = dFactory.newDocumentBuilder();
           Document doc;
           doc = builder.parse(new File("homework-13/config.xml"));
           NodeList nl = doc.getElementsByTagName("className");
           Node classNode = nl.item(0).getFirstChild();
           String cName = classNode.getNodeValue();
           Class c = Class.forName(cName);
           Object obj = c.newInstance();
           return obj;
       } catch (Exception e) {
           e.printStackTrace();
           return null;
       }
   }
}



<?xml version="1.0" encoding="UTF-8"?>
<config>
<!--    <className>three.FADepartment</className>-->
   <className>three.HRDepartment</className>
</config>



abstract class Department {
   public abstract void visit(FullTimeEmployee employee);
   public abstract void visit(PartTimeEmployee employee);
}


//人力资源部:
class HRDepartment extends Department {

   public void visit(FullTimeEmployee employee) {
       int workTime = employee.getWorkTime();
       System.out.println("正式员工" + employee.getName() + "实际工作时间为:" + workTime + "小时。");
       if (workTime > 40) {
           System.out.println("正式员工" + employee.getName() + "加班时间为:" + (workTime - 40) + "小时。");
       } else if (workTime < 40) {
           System.out.println("正式员工" + employee.getName() + "请假时间为:" + (40 - workTime) + "小时。");
       }
   }

   public void visit(PartTimeEmployee employee) {
       int workTime = employee.getWorkTime();
       System.out.println("临时工" + employee.getName() + "实际工作时间为:" + workTime + "小时。");
   }
}



//财务部:
class FADepartment extends Department {
   public void visit(FullTimeEmployee employee) {
       int workTime = employee.getWorkTime();
       double weekWage = employee.getWeeklyWage();
       if (workTime > 40) {
           weekWage = weekWage + (workTime - 40) * 100;
       } else if (workTime < 40) {
           weekWage = weekWage - (40 - workTime) * 80;
           if (weekWage < 0) {
               weekWage = 0;
           }
       }
       System.out.println("正式员工" + employee.getName() + "实际工资为:" + weekWage + "元。");
   }

   public void visit(PartTimeEmployee employee) {
       int workTime = employee.getWorkTime();
       double hourWage = employee.getHourWage();
       System.out.println("临时工" + employee.getName() + "实际工资为:" + workTime * hourWage + "元。");
   }

}



=================================================

interface Employee {
   public void accept(Department handler); //接受一个抽象访问者访问
}



import java.util.ArrayList;
class EmployeeList {
   private ArrayList<Employee> list = new ArrayList<Employee>();
   public void addEmployee(Employee employee) {
       list.add(employee);
   }
   public void accept(Department handler) {
       for (Object obj : list) {
           ((Employee) obj).accept(handler);
       }
   }

}



class FullTimeEmployee implements Employee {
   private String name;
   private double weeklyWage;
   private int workTime;

   public FullTimeEmployee(String name, double weeklyWage, int workTime) {
       this.name = name;
       this.weeklyWage = weeklyWage;
       this.workTime = workTime;
   }
   public void setName(String name) {
       this.name = name;
   }
   public void setWeeklyWage(double weeklyWage) {
       this.weeklyWage = weeklyWage;
   }
   public void setWorkTime(int workTime) {
       this.workTime = workTime;
   }
   public String getName() {
       return (this.name);
   }
   public double getWeeklyWage() {
       return (this.weeklyWage);
   }
   public int getWorkTime() {
       return (this.workTime);
   }

   public void accept(Department handler) {
       handler.visit(this); 
   }

}



class PartTimeEmployee implements Employee {
   private String name;
   private double hourWage;
   private int workTime;
   public PartTimeEmployee(String name, double hourWage, int workTime) {
       this.name = name;
       this.hourWage = hourWage;
       this.workTime = workTime;
   }
   public void setName(String name) {
       this.name = name;
   }
   public void setHourWage(double hourWage) {
       this.hourWage = hourWage;
   }
   public void setWorkTime(int workTime) {
       this.workTime = workTime;
   }
   public String getName() {
       return (this.name);
   }
   public double getHourWage() {
       return (this.hourWage);
   }
   public int getWorkTime() {
       return (this.workTime);
   }


   public void accept(Department handler) {
       handler.visit(this); 
   }

}

3、代码运行效果图 image.png