2008年下半年软件设计师考试下午试题最后一题考查模板方法模式,原题如下:
【全国计算机技术与软件专业技术资格(水平)考试 2008年下半年 软件设计师 下午试卷】
注:当年试题五、试题六和试题七三选一,试题六为C++版,试题七为Java版。
试题六
阅读以下说明和 C++代码,将应填入 (n) 处的字句写在答题纸的对应栏内。
【说明】
已知某类库开发商提供了一套类库,类库中定义了Application类和Document类,它们之间的关系如图6-1所示,其中,Application类表示应用程序自身,而Document类则表示应用程序打开的文档。Application类负责打开一个已有的以外部形式存储的文档,如一个文件,一旦从该文件中读出信息后,它就由一个Document对象表示。
图6-1 Application与Document关系图
当开发一个具体的应用程序时,开发者需要分别创建自己的Application和Document子类,例如图6-1中的类MyApplication和类MyDocument,并分别实现Application和Document类中的某些方法。
已知Application类中的openDocument方法采用了模板方法(Template Method)设计模式,该方法定义了打开文档的每一个步骤,如下所示:
1. 首先检查文档是否能够被打开,若不能打开,则给出出错信息并返回;
2. 创建文档对象;
3. 通过文档对象打开文档;
4. 通过文档对象读取文档信息;
5. 将文档对象加入到Application的文档对象集合中。
【C++代码】
#include <iostream>
#include <vector>
using namespace std;
class Document{
public:
void save() { /*存储文档数据,此处代码省略*/ }
void open(string docName) { /* 打开文档,此处代码省略 */ }
void close() { /* 关闭文档,此处代码省略*/ }
virtual void read(string docName) = 0;
};
class Appplication{
private:
vector < (1) > docs; /*文档对象集合*/
public:
bool canOpenDocument(string docName) {
/*判断是否可以打开指定文档,返回真值时表示可以打开,
返回假值表示不可打开,此处代码省略*/
}
void addDocument(Document * aDocument){
/*将文档对象添加到文档对象集合中*/
docs.push_back( (2) );
}
virtual Document * doCreateDocument() = 0; /*创建一个文档对象*/
void openDocument(string docName){ /*打开文档*/
if ( (3) ){
cout << "文档无法打开 !" << endl;
return;
}
(4) adoc = (5) ;
(6) ;
(7) ;
(8) ;
}
};
试题七
阅读以下说明以及Java程序,将应填入 (n) 处的字句写在答题纸的对应栏内。
【说明】
已知某类库开发商提供了一套类库,类库中定义了Application类和Document类,它们之间的关系如图7-1所示,其中,Application类表示应用程序自身,而Document类则表示应用程序打开的文档。Application类负责打开一个已有的以外部形式存储的文档,如一个文件,一旦从该文件中读出信息后,它就由一个Document对象表示。
图7-1 Application与Document关系图
当开发一个具体的应用程序时,开发者需要分别创建自己的Application和Document子类,例如图7-1中的类MyApplication和类MyDocument,并分别实现Application和Document类中的某些方法。
已知Application类中的openDocument方法采用了模板方法(Template Method)设计模式,该方法定义了打开文档的每一个步骤,如下所示:
1. 首先检查文档是否能够被打开,若不能打开,则给出出错信息并返回;
2. 创建文档对象;
3. 通过文档对象打开文档;
4. 通过文档对象读取文档信息;
5. 将文档对象加入到Application的文档对象集合中。
【Java代码】
abstract class Document {
public void save() { /* 存储文档数据,此处代码省略 */}
public void open(String docName) { /*打开文档,此处代码省略 */}
public void close() { /* 关闭文档,此处代码省略 */}
public abstract void read(String docName);
}
abstract class Application {
private Vector< (1) > docs; /*文档对象集合*/
public boolean canOpenDocument(String docName){
/*判断是否可以打开指定文档,返回真值时表示可以打开,
返回假值表示不可打开,此处代码省略*/
}
public void addDocument(Document aDocument){
/*将文档对象添加到文档对象集合中*/
docs.add( (2) );
}
public abstract Document doCreateDocument(); /*创建一个文档对象*/
public void openDocument(String docName) { /*打开文档*/
if( (3) ) {
System.out.println("文档无法打开!");
return;
}
(4) adoc = (5) ;
(6) ;
(7) ;
(8) ;
}
}
------------------------------------------------------------------------------------------------------------------------------------------------------
分析与解答:
本题是模板方法模式的一个应用实例,相对于只有抽象父类和具体子类的模板方法模式的简单结构而言,本题适当增加了难度,引入了一个外部继承等级结构(Document和MyDocument)用来实现更复杂的文件操作(实质上是与工厂方法模式联用,)。在本题中,由于在Application类中包含了模板方法openDocument(),因此Application类充当抽象父类,其子类MyApplication充当具体子类。
下面我们分析一下Application类中的几个方法:
(1) canOpenDocument()和addDocument()方法是具体方法;
(2) doCreateDocument()方法是抽象方法;
(3) openDocument()方法是模板方法,在openDocument()方法中定义了其他方法的执行顺序。
不难发现,在一个Application中可以包含多个Document对象,在程序中使用一个vector(Vector)类型的集合对象docs来存储一系列文档对象,因此第(1)空答案为:Document*(C++)或Document(Java)。根据代码注释,addDocument()方法用于将一个文档对象添加到文档对象集合(向量docs)中,在该方法内部将调用向量对象docs的相应方法将文档增加到其中,因此,第(2)空为addDocument()方法中所传入的参数aDocument。
从第(3)空开始,本题重点考查模板方法openDocument()的设计与实现,根据题意,该方法包含五个步骤,首先检查文档是否能够被打开,而canOpenDocument()方法正用于此用途,返回真值表示可以打开,否则不能打开,而只有在打开文件之后才能执行文档读取等操作,如果不能打开则提示错误信息并结束方法的执行,因此第(3)空应为当canOpenDocument()为假值的条件判断,即!canOpenDocument(docName)。如果文件能够打开,则继续执行后续步骤,先创建一个文档对象,类型为Document*(C++)或Document(Java)【第(4)空】,根据题意,Document类型的文档对象不需要直接通过实例化来创建,可以通过doCreateDocument()方法来创建,不同的Application的子类有不同的创建方法,可以创建不同类型的Document的子类的对象,从这一点来看,此题还隐含应用了一个工厂方法模式,Document充当抽象产品,MyDocument充当具体产品,Application充当抽象工厂,MyApplication充当具体工厂,doCreateDocument()方法即为工厂方法,因此第(5)空为doCreateDocument()。
在创建好文档对象之后,需要通过文档对象adoc打开文档并读取文档信息,因此第(6)空为调用文档对象adoc的open()方法打开文档,第(7)空为调用文档对象adoc的read()方法读取文档信息。最后需要将文档对象adoc加入到Application的文档对象集合中,因此第(8)空将调用addDocument()方法将adoc增加到集合中,当然直接调用docs的方法来实现增加操作也未尚不可。(个人觉得第(8)空并不严谨,)
推荐:深入学习模板方法模式
参考答案:
【试题六】
(1) Document*
(2) aDocument
(3) !canOpenDocument(docName)
(4) Document*
(5) doCreateDocument()
(6) adoc->open(docName)
(7) adoc->read(docName)
(8) addDocument(adoc)或docs.push_back(adoc)
【试题七】
(1) Document
(2) aDocument
(3) !canOpenDocument(docName)
(4) Document
(5) doCreateDocument()
(6) adoc.open(docName)
(7) adoc.read(docName)
(8) addDocument(adoc)或docs.add(adoc)
【作者:刘伟 http://blog.csdn.net/lovelion】