系列文章目录
1.【软考之软件设计师】PPT课件
2.【软考之软件设计师】学习笔记
3.【软考之软件设计师】上午题—信管网(每天更新)
4.【软考之软件设计师】上午题—希赛网(每天更新)
5.【软件设计师真题】下午题第一大题—数据流图设计
6.【软件设计师真题】下午题第二大题—数据库设计
7.【软件设计师真题】下午题第三大题—UML 分析与设计
8.【软件设计师真题】下午题第四大题—算法设计
9.【软件设计师真题】下午题第五大题—面向对象程序设计
掌握 C++、Java 中任一种程序设计语言,以便能指导程序员进行编程和测试,并进行必要的优化。
一、真题一
1、题目
阅读下列说明和Java代码,将应填入(n)处的子句写在答题纸的对应栏内。
【说明】(15 分)
现要求实现一个能够自动生成求职简历的程序,简历的基本内容包括求职者的姓名、性别、年龄及工作经历。希望每份简历中的工作经历有所不同,并尽量减少程序中的重复代码。
现采用原型模式(Prototype)来实现上述要求,得到如图 6-1 所示的类图。
【Java 代码】
Class WorkExperience (1) Cloneable{ //工作简历
Private String workDate;
Private String company;
Public obiect Clone(){
(2);
obj.workDate=this.workDate;
Obj.company=this.company;
Return obj;
}
}
Class Resume (3) Cloneable{ //简历
Private String name;
Private String sex;
Private String age;
Private WorkExperience work;
Public Resume(string name){
This.name = name;
work=new workExperience();
}
Private Resume(WorkExperience work){
This.work=(4);
}
Public void SetPersonalInfo(String sex,String age)
{ /*代码省略*/}
Public void SetworkExperience (String workDate,string company)
{/*代码省略*/}
Public Obiect Clone(){
Resume obj= (5) ;
//其余代码省略
Return obj;
}
}
Class WorkResume{
Public static void main(string[]args){
Resume a=new Resume("张三");
a.SetPersonalInfo("男”"29");
a.SetworkExperience("1998~2000","XXX公司");
Resume b=(6);
b.SetworkExperience("2001~2006","YYY公司");
}
}
2、解析
本题考查原型模式的概念及应用。原型模式是一种对象创建模型,用原型实体指定创建对象的种类,并且通过复制这些原型创建新的对象。原型模式允许一个对象再创建另一个可定制的对象,无须知道任何创建的细节。
也就是说,在Resume a,Resume b大量的信息,也就是姓名、年龄这些类成员是完全一样的的,只有里面的WorkExperience中的内容,但你不可以在初始化Resume a与Resume b的时候,搞出Resume a(“张三”,“29”,"男“,“1999-2002”,“XX公司”),Resume b(“张三”,“29”,“男“,“2002-2006”,“YY公司”)公司这样的初始化来,需要Resume b直接复制Resume a的内容,然后利用其中的set的方法,来改变其中的"1999-2002”,"XX公司"两项。
据说使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
其中用到Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型。这比C++还要自己定义一个Cloneable接口简单得多,因为Java本身自带。
题中WorkExperience类和Resume类需要实现Cloneable接口,故空(1)处和空(3)处应填入implements。WorkExperience中需要实现Clone方法,并将自身复制一份,由下面的代码可知空(2)处应填入WorkExperience obj = new WorkExperience()。Resume类中的私有构造方法实现WorkExperience的深复制,故空(4)处应填入(WorkExperience)work.Clone()。而Resume类中的Clone方法实现自身的复制,故空(5)处应填入new Resume(this.work)。main中实现Resume b对a的复制,故空(6)处应填入a.Clone()。
3、答案
class WorkExperience implements Cloneable{
private String workDate;
private String company;
public Object Clone(){
WorkExperience obj= new WorkExperience();
obj.workDate=this.workDate;
obj.company=this.company;
return obj;
}
//getter setter,只是为了数据的传递。原题目这段代码被省略了。
public String getWorkDate() {
return workDate;
}
public void setWorkDate(String workDate) {
this.workDate = workDate;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
}
class Resume implements Cloneable{
private String name;
private String sex;
private String age;
private WorkExperience work;
public Resume(String name){//初始化的时候,WorkExperience为空
this.name=name;
work=new WorkExperience();
}
private Resume(WorkExperience work){
//构建Resume类的时候,自动将所有的WorkExperience信息复制过去
this.work=work;
}
public void SetPersonalInfo(String sex,String age){
this.sex=sex;
this.age=age;
}
public void SetWorkExperience(String workDate,String company){//用于改变WorkExperience信息
work.setWorkDate(workDate);
work.setCompany(company);
}
public Object Clone(){//复制原型的时候,将WorkExperience信息+所有类成员复制过去。
Resume obj= new Resume(work);
obj.name=this.name;
obj.sex=this.sex;
obj.age=this.age;
return obj;
}
//getter setter,只是为了数据的传递。原题目这段代码被省略了。
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public WorkExperience getWork() {
return work;
}
public void setWork(WorkExperience work) {
this.work = work;
}
}
public class WorkResume {
public static void main(String[] args) {
//Resume a成功构建,并设置信息之后
Resume a= new Resume("张三");
a.SetPersonalInfo("男","29");
a.SetWorkExperience("1998-2000", "XXX公司");
//Resume b直接复制a信息,再改变SetWorkExperience
Resume b=(Resume)a.Clone();
b.SetWorkExperience("2001-2006", "YYY公司");
//打印测试Resume b的信息
System.out.println(b.getName()+","+b.getAge()+","+b.getSex()+","+b.getWork().getWorkDate()+","+b.getWork().getCompany());
}
}
b并没有初始化,只是直接拷贝a的内容,改变工作经历,但打印B的信息,发现B的信息正是我们想要的,证明原型模式构建成功。
二、真题二
1、题目
阅读下列说明和 C++代码,将应填入(n)处的字句写在答题纸的对应栏内。
【说明】
生成器(Builder)模式的意图是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。图 5-1 所示为其类图。
【Java代码】
import java.util.*;
class Product {
private String partA;
private String partB;
public Product() {};
public void setPartA(String s) { partA = s; }
public void setPartB(String s) { partB = s; }
}
interface Builder {
public (1) ;
public void buildPartB();
public (2) ;
}
class ConcreteBuilder1 implements Builder {
private Product product;
public ConcreteBuilder1() {
product = new Product();
}
public void buildPartA() { (3) ("Component A"); }
public void buildPartB() { (4) ("Component B"); }
public Product getResult() { return product;}
}
class ConcreteBuilder2 implements Builder {
// 代码省略
}
class Director {
private Builder builder;
public Director(Builder builder) {this.builder = builder; }
public void construct() {
(5) ;
// 代码省略
}
}
class Test {
public static void main(String[] args) {
Director director1 = new Director(new ConcreteBuilder1());
director1.construct();
}
}
2、解析
本题考查的是面向对象程序设计,是JAVA语言与设计模式的结合考查。本题涉及的设计模式是构建器模式(建造者模式),将复杂类的构造过程推迟到子类实现。
对于第一空、第二空,根据实现接口的类,补充其接口缺失的方法,因此,空(1)和空(2)分别填写void buildPartA()和Product getResult(),二者可以互换;
对于第三空、第四空,是根据product类方法进行的补充,与具体产品的实现保持一致,因此,分别填写, product.setPartA, product.setPartB;
对于第五空,由于在填空后面跟随的是代码省略,因此题目并不严谨,缺失的语句可以有builder.buildPartA(); builder.buildPartB()。
3、答案
(1)void buildPartA()
(2)Product getResult()
(3)product.setPartA
(4)product.setPartB
(5) builder.buildPartA() 或 builder.buildPartB()
三、真题三
1、题目
阅读下列说明和Java代码,将应填入(n)处的字句写在答题纸的对应栏内。
【说明】
某图像预览程序要求能够查看BMP、JPEG和GIF三种格式的文件,且能够在Windows和Linux两种操作系统上运行。程序需具有较好的扩展性以支持新的文件格式和操作系统。为满足上述需求并减少所需生成的子类数目,现采用桥接(Bridge)模式进行设计,得到如下图所示的类图。
【Java代码】
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 JPEGImage extends Image{
//此处代码省略
};
class Main{
public static void main(String[]args) {
// 在 Linux 操作系统上查看 demo.gif 图像文件
Image image= (3) ;
Implementor imageImp= (4) ;
(5) ;
Image.parseFile("demo.gif");
}
}
2、解析
第一空是显示像素矩阵 m
从类图来看 Implementor是WinImp和LinuxImp两子类的父类。那就需要从子类中去找共同的方法,然后把它们抽象出来。
共同的方法为: void doPaint(Matrix m) ;抽象就成了 abstract void doPaint(Matrix m);此处别忘了abstract关键字。是抽象方法。
第二空是显示像素矩阵m
在Image的类和其子类中,要显示像素矩阵,可以使用调用Implementor类的方法doPaint,而Image类中定义了对象imp。
即调用的方法为: imp.doPaint(m)
第三空是构造出Gif图像的对象 new GIFImage()
第四空是要在Linux操作系统上查看,需要一个LinuxImp的对象 . new LinuxImp()
第五空是把imageImp对象传递,以便能够查看Gif图像文件,image.setImp(imageImp)
3、答案
1.abstract void doPaint(Matrix m)
2.imp.doPaint(m)
3.new GIFImage()
4.new LinuxImp()
5.image.setImp(imageImp)
四、真题四
1、题目
阅读下列说明和JAVA代码,将应填入(n)处的字句写在答题纸的对应栏内。
【说明】
Facade(外观)模式是一种通过为多个复杂子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式,以医院为例,就医时患者需要与医院不同的职能部门交互,完成挂号、门诊、取药等操作。为简化就医流程,设置了一个接待员的职位,代患者完成上述就医步骤,患者则只需与接待员交互即可。如图6-1给出了以外观模式实现该场景的类图。
【Java 代码】
import java.util.*;
interface Patient {
( 1 );
}
interface Disposer{
( 2 );
}
class Registry implements Disposer{ //挂号
public void dispose(Patient patient) {
System.out.println("I am registering..."+patient.getName());
}
}
class Doctor implements Disposer { //医生门诊
public void dispose(Patient patient) {
System.out.println("I am diagnosing..."+ patient.getName());
}
}
class Pharmacy implements Disposer { //取药
public void dispose(Patient patient) {
System.out.println("I am giving medicine..."+ patient.getName());
}
}
class Facade {
private Patient patient;
public Facade(Patient patient) { this.patient=patient;}
public void dispose(){
Registry registry=new Registry();
Doctor doctor=new Doctor();
Pharmacy ph=new Pharmacy();
registry.dispose(patient);
doctor.dispose(patient);
ph.dispose(patient);
}
}
class ConcretePatient implements Patient {
private String name;
public ConcretePatient(String name) { this.name=name;}
public String getName() { return name;}
}
class FacadeTest{
public static void main(String[] args) {
Patient patient=( 3 );
( 4 ) f =( 5 );
( 6 );
}
}
2、解析
interface Patient{
public abstract String getName();//填空1
}
interface Disposer{
public abstract void dispose(Patient patient);//填空2
}
class Resgistry implements Disposer{
public void dispose(Patient patient){
System.out.println("I am registering..."+patient.getName());
}
}
class Doctor implements Disposer{//医生门诊
public void dispose(Patient patient){
System.out.println("I am diagnosing..."+patient.getName());
}
}
class Pharmacy implements Disposer{//取药
public void dispose(Patient patient){
System.out.println("I am medicine..."+patient.getName());
}
}
class Facade{
private Patient patient;
public Facade(Patient patient) {
this.patient = patient;
}
public void dispose(){
Resgistry resgistry=new Resgistry();
Doctor doctor= new Doctor();
Pharmacy ph=new Pharmacy();
resgistry.dispose(patient);
doctor.dispose(patient);
ph.dispose(patient);
}
}
class ConcretePatient implements Patient{
private String name;
public ConcretePatient(String name) {
this.name = name;
}
public String getName(){
return name;
}
}
public class PatientTest {
public static void main(String[] args) {
Patient patient = new ConcretePatient("name");//填空3
Facade f = new Facade(patient);//填空4、5
f.dispose();//填空6
}
}
//输出
// I am registering...name
// I am diagnosing...name
// I am medicine...name
3、答案
五、真题五
1、题目
阅读下列说明和Java代码,将应填入(n)处的字句写在答题纸的对应栏内。
【说明】
在软件系统中,通常会给用户提供取消、不确定或者错误操作的选择,允许将系统恢复到原先的状态。现使用备忘录(Memento)模式实现该要求,得到如图5-1所示的类图。Memento 包含了要被恢复的状态。Originator创建并在Memento中存储状态。Caretaker负责从Memento中恢复状态。
import java.util.*;
class Memento {
private String state;
public Memento (String state) {this.state=state;}
public String getState() {return state; }
}
class Originator{
private String state;
public void setState (String state) {this.state=state; }
public String getState() { retum state; }
public Memento saveStateToMemento() { Return ( 1 ) }
public void getStateFromMemento(Memento Memento){ state =( 2 )}
}
class CareTaker {
public ( 3 ){
mementoList.add(state);
}
public ( 4 ) {
return mementoList get(index);
}
}
class MementoPatternDemo{
pubic static void main (String[] args) {
Originator aniginator=new Originator();
CareTaker careTaker =new careTaker();
originator.setState("State #1");
originator.setState("State #2");
careTaker.add( 5 )
originator.setState("State #3");
careTaker.add ( 6 )
originator.setState("State #4");
System.out.printIn("Current State"+originator.getState());
originator.getStateFromMemento(careTaker.get(0));
System.out.println("Frist saved State"+originator.getState());
originator.getStateFromMemento(careTaker.get(1));
System.out.println("Second saved State"+originator.getState());
2、解析
import java.util.*;
class Memento {
private String state;
public Memento (String state) {this.state=state;}
public String getState() {return state; }
}
class Originator{
private String state;
public void setState (String state) {this.state=state; }
public String getState() { return state; }
public Memento saveStateToMemento() {
return new Memento(state);//填空1
}
public void getStateFromMemento(Memento Memento){
state = Memento.getState() ;//填空2
}
}
class CareTaker {
public void add(Memento state){
mementoList.add(state);
}
public Memento get(int index){
return mementoList.get(index);
}
}
class MementoPatternDemo{
public static void main (String[] args) {
Originator originator = new Originator();
CareTaker careTaker = new CareTaker();
originator.setState("State #1");
originator.setState("State #2");
careTaker.add(originator.saveStateToMemento());//填空5
originator.setState("State #3");
careTaker.add(originator.saveStateToMemento());//填空5
originator.setState("State #4");
}
}
public class MementoDemo{
}
3、答案
六、真题六
1、题目
阅读下列说明和Java代码,将应填入(n)处的字句写在答题纸的对应栏内。
【说明】
享元(FlyWeight)模式主要用于减少创建对象的数量,以降低内存占用,提高性能。先要开发一个网络围棋程序,允许多个玩家联机下棋。由于只有一台服务器,为节省内存空间,采用享元模式实现该程序,得到如图6-1所示的类图。
import java.util.*;
enum PieceColor {BLACK, WHITE} // 棋子颜色
class PiecePos { // 棋子位置
private int x;
private int y;
public PiecePos(int a, int b) {
x = a;
y = b;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
abstract class Piece { // 棋子定义
protected PieceColor m_color; // 颜色
protected PiecePos m_pos; // 位置
public Piece(PieceColor color, PiecePos pos) {
m_color = color;
m_pos = pos;
}
(1);
}
class BlackPiece extends Piece {
public BlackPiece(PieceColor color, PiecePos pos) {
super(color, pos);
}
public void draw() {
System.out.println("draw a blackpiece");
}
}
class WhitePiece extends Piece {
public WhitePiece(PieceColor color, PiecePos pos) {
super(color, pos);
}
public void draw() {
System.out.println("white a blackpiece");
}
}
class PieceBoard { // 棋盘上已有的棋子
private static final ArrayList<(2)> m_arrayPiece = new ArrayList<>;
private String m_blackName; // 黑方名称
private String m_whiteName; // 白方名称
public PieceBoard(String black, String white) {
m_blackName = black;
m_whiteName = white;
}
// 一步棋,在棋盘上放一颗棋子
public void SetPiece(PieceColor color, PiecePos pos) {
(3) piece = null;
if (color == PieceColor.BLACK) { // 放黑子
piece = new BlackPiece(color, pos); // 获取一颗黑子
System.out.println(m_blackName + "在位置(" + pos.getX() + ","
+ pos.getY() + ")");
(4);
} else { // 放白子
piece = new WhitePiece(color, pos); // 获取一颗白子
System.out.println(m_whiteName + "在位置(" + pos.getX() + ","
+ pos.getY() + ")");
(5);
}
m_arrayPiece.add(piece);
}
}
2、解析
import java.util.*;
enum PieceColor {BLACK, WHITE} // 棋子颜色
class PiecePos { // 棋子位置
private int x;
private int y;
public PiecePos(int a, int b) {
x = a;
y = b;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
abstract class Piece { // 棋子定义
protected PieceColor m_color; // 颜色
protected PiecePos m_pos; // 位置
public Piece(PieceColor color, PiecePos pos) {
m_color = color;
m_pos = pos;
}
public abstract void draw(); //填空1
}
class BlackPiece extends Piece {
public BlackPiece(PieceColor color, PiecePos pos) {
super(color, pos);
}
public void draw() {
System.out.println("draw a black piece");
}
}
class WhitePiece extends Piece {
public WhitePiece(PieceColor color, PiecePos pos) {
super(color, pos);
}
public void draw() {
System.out.println("draw a white piece");
}
}
class PieceBoard { // 棋盘上已有的棋子
private static final ArrayList<Piece> m_arrayPiece = new ArrayList<>();//填空2
private String m_blackName; // 黑方名称
private String m_whiteName; // 白方名称
public PieceBoard(String black, String white) {
m_blackName = black;
m_whiteName = white;
}
// 一步棋,在棋盘上放一颗棋子
public void SetPiece(PieceColor color, PiecePos pos) {
Piece piece = null;//填空3
if (color == PieceColor.BLACK) { // 放黑子
piece = new BlackPiece(color, pos); // 获取一颗黑子
System.out.println(m_blackName + "在位置(" + pos.getX() + ","
+ pos.getY() + ")");
piece.draw();//填空4
} else { // 放白子
piece = new WhitePiece(color, pos); // 获取一颗白子
System.out.println(m_whiteName + "在位置(" + pos.getX() + ","
+ pos.getY() + ")");
piece.draw();//填空5
}
m_arrayPiece.add(piece);
}
}
public class PieceTest {
public static void main(String[] args) {
PiecePos piecePos=new PiecePos(3,4);
PieceBoard pieceBoard = new PieceBoard("black","white");
pieceBoard.SetPiece(WHITE ,piecePos);
}
}
//输出结果:
// white在位置(3,4)
// draw a white piece
3、答案
七、真题七
1、题目
阅读下列说明和Java代码,将应填入(n)处的字句写在答题纸的对应栏内。
【说明】
层叠菜单是窗口风格的软件系统中经常采用的一种系统功能组织方式。层叠菜单 (如图6-1示例)中包含的可能是一个菜单项(直接对应某个功能),也可能是一个子菜单,现在采用组合(composite)设计模式实现层叠菜单,得到如图6-2所示的类图。
import java.util.*;
abstract class MenuComponent{//构成层叠菜单的元素
(1) String name;//菜单项或子菜单名称
public void printName(){System.out.println(name);}
public (2);
public abstract boolean removeMenuElement(MenuComponent element);
public (3);
}
Class Menu extends MenuComponent{
public MenuItem(String name){this.name=name;}
public boolean addComponent(MenuComponent element){return false;}//(2)
public boolean removeComponent(MenuComponent element){return false;}
public List<MenuComponent> getElement(){return null;}//(3)
}
Class MenuItem extends MenuComponent{
public (4);
public MenuItem(String name){
this.name=name;
this.elementList = new ArrayList<MenuComponent>();
}
public boolean addMenuElement(MenuComponent element){
return elementList.add(element);
}
public boolean removeMenuElement(MenuComponent element){
return elementList.remove(element);
}
public List<MenuComponent> getElement(){return elementList;}
}
Class CompositeTest{
public static void main(String[] args){
MenuComponent mainMenu = new Menu("Insert");
MenuComponent subMenu = new Menu("Chart");
MenuComponent element = new MenuItem("On This Sheet");
(5);
subMenu.addMenuElement(element);
printMenus(mainMenu);
}
private static void printMenus(MenuComponent ifile){
ifile.printName();
List<MenuComponent> children = ifile.getElement();
if(children==null) return;
for(MenuComponent element:children){
printMenus(element);
}
}
}
2、解析
import java.util.*;
abstract class MenuComponent{//构成层叠菜单的元素
protected String name;//菜单项或子菜单名称 //填空1
public void printName(){System.out.println(name);}
public abstract boolean addMenuElement(MenuComponent element);//填空2
public abstract boolean removeMenuElement(MenuComponent element);
public abstract List<MenuComponent> getElement();//填空3
}
class MenuItem extends MenuComponent{
public MenuItem(String name){this.name=name;}
@Override
public boolean addMenuElement(MenuComponent element) {
return false;
}
@Override
public boolean removeMenuElement(MenuComponent element) {
return false;
}
public List<MenuComponent> getElement(){return null;}
}
class Menu extends MenuComponent{
public ArrayList<MenuComponent> elementList;//填空4
public Menu(String name){
this.name=name;
this.elementList = new ArrayList<MenuComponent>();
}
public boolean addMenuElement(MenuComponent element){
return elementList.add(element);
}
public boolean removeMenuElement(MenuComponent element){
return elementList.remove(element);
}
public List<MenuComponent> getElement(){return elementList;}
}
class CompositeTest{
public static void main(String[] args){
MenuComponent mainMenu = new Menu("Insert");
MenuComponent subMenu = new Menu("Chart");
MenuComponent element = new MenuItem("On This Sheet");
mainMenu.addMenuElement(subMenu);//填空5
subMenu.addMenuElement(element);
printMenus(mainMenu);
}
private static void printMenus(MenuComponent ifile){
ifile.printName();
List<MenuComponent> children = ifile.getElement();
if(children==null) return;
for(MenuComponent element:children){
printMenus(element);
}
}
}
3、答案
(1)protected;
(2)abstract boolean addMenuElement( MemuComponent element);
(3)abstract List < MenuComponent > getElement();
(4)Arraylist < MenuComponent > elementList;
(5)mainMenu.addMenuElement(subMenu);
八、真题八
1、题目
阅读下列说明和Java代码,将应填入(n)处的字句写在答题纸的对应栏内。
【说明】
在线支付是电子商务的一个重要环节,不同的电子商务平台提供不同的支付接口,现在需要给不同的商务平台的支付接口,使得客户在不同平台购物时, 不需要关系具体的支付接口。拟采用中介在( Mediator )设计模式来实现该需求,所设计的类图如图6-1所示
interface WebServiceMediator{
public (1);//填空1
public void SetAmazon(WebService amazon);
public void SetEbay(WebService ebay);
}
abstract class WebService{
protected (2) mediator;//填空2
public abstract void SetMediator(WebServiceMediator mediator);
public (3);//填空3
public abstract void search(double money);
}
class ConcreteMediator implements WebServiceMediator{
private WebService amazon;
private WebService ebay;
public ConcreteMediator() {
amazon = null;
ebay = null;
}
@Override
public void SetAmazon(WebService amazon) {
this.amazon=amazon;
}
@Override
public void SetEbay(WebService ebay) {
this.ebay=ebay;
}
public void buy(double money,WebService service){
if (service == amazon)
amazon.search(money);
else
ebay.search(money);
}
}
class Amazon extends WebService{
@Override
public void SetMediator(WebServiceMediator mediator) {
this.mediator=mediator;
}
@Override
public void buyService(double money) {
(4);//填空4
}
@Override
public void search(double money) {
System.out.println("Amazon receive: "+money);
}
}
class Ebay extends WebService{
@Override
public void SetMediator(WebServiceMediator mediator) {
this.mediator=mediator;
}
@Override
public void buyService(double money) {
}
@Override
public void search(double money) {
(5);//填空5
}
}
public class WebServiceTest {
public static void main(String[] args) {
}
}
2、解析
(1)空是属于接口WebServiceMeditor内的方法,我们可以通过下文的实现类中找到ConcreteServiceMeditor可知缺少了一个buy()方法
故第一空填写void buy(double money, WebService service);(2)空类WebService中属性的参数类型,Colleague与Mediator之间的关联关系由属性meditor实现,所以第2空应该填写WebServiceMediator;(3)空类WebService中的抽象方法,根据其具体子类可以看到缺少的是buyService方法,书写成 abstract void buyService(double money);(4)空和(5)空具体同事类Amazon、Ebay与中介者的通信,调用中介者之间的支付接口,所以空(4)和(5)都填写mediator.buy(money, this)。
import java.util.*;
interface WebServiceMediator { //1.1 看到(1)是接口,那么我们就去谁实现了这个WebServiceMediator接口,会发现只有ConcreteServiceMediator实现了这个接口,那么我们就去ConcreteServiceMediator这个类中找答案
public (1) ; // 1.4 答案:void buy(double money, WebService service)
public void SetAmazon(WebService amazon);
public void SetEbay(WebService ebay);
}
abstract class WebService {
// 2.1 看到这种定义数据类型的,你可以看看在同一个类中,有没有被定义,你会发现(2)的下一行就定义了mediator类型,如果你不确定,你继续看其他有这个单词mediator前面被定义的是什么类型,你会发现都是WebServiceMediator,那么就直接抄WebServiceMediator进去即可。
protected (2) mediator; // (2)答案:WebServiceMediator
public abstract void SetMediator(WebServiceMediator mediator);
// 3.1 是abstract抽象类,那么谁继承它,就去谁那里找,有两个继承它(一般有两个继承它,就去找两个相同的方法并且没有出现在这个抽象类中),找这个abstract class WebService抽象类中没有被定义的方法。
public (3) ; // (3)答案:abstract void buyService(double money)
public abstract void search(double money);
}
class ConcreteServiceMediator implements WebServiceMediator {
private WebService amazon;
private WebService ebay;
public ConcreteServiceMediator() {
amazon = null;
ebay = null;
}
public void SetAmazon(WebService amazon) { // 1.2 找(1)答案,这个出现了排除掉
this.amazon = amazon;
}
public void SetEbay(WebService ebay) { // 1.2 找(1)答案,这个也出现了,也可以排除掉
this.ebay = ebay;
}
public void buy(double money, WebService service) { // 1.3 找(1)答案,ok这个没有出现在接口WebServiceMediator中,那么就填它!直接将整个方法抄进去,不要抄方法体
if (service == amazon)
amazon.search(money);
else
ebay.search(money);
}
}
class Amazon extends WebService {
public void SetMediator(WebServiceMediator mediator) { // 3.2 出现了在抽象类abstract class WebService中可以排除
this.mediator = mediator;
}
public void buyService(double money) { // 3.4 只剩下这个没有出现在抽象类中,有可能这个是答案,如果不确定就去另一个继承它的类EBay验证答案
// 4.1【理解分析题】 因为是中介者模式,你购买东西就必须通过中介,而此方法中买这个服务,中介中有buy方法,那么就可以通过中介者来实现买,又因为SetMediator(WebServiceMediator mediator)定义的mediator都没有被用过,出题者一般不会给无用的信息出现多次并且还没有用过,因此这里可以通过中介者调用方法来实现买buy,即mediator.buy(money,this)
(4) ; // 答案:mediator.buy(money,this)
}
public void search(double money) { // 3.3 出现了可以排除
System.out.println("Amazon receive:" + money);
}
}
class Ebay extends WebService {
public void SetMediator(WebServiceMediator mediator) {
this.mediator = mediator;
}
public void buyService(double money) { // 3.5 你会发现,这个类也是两个方法都在抽象类中,只有这个buyService不在,那么答案只会是这个!
// (5)【理解分析题】
(5) ; // 答案:mediator.buy(money,this)
}
public void search(double money) {
System.out.println("Ebay receive:" + money);
}
}
3、答案
(1) void buy(double money, WebService service)
(2) WebServiceMediator
(3) abstract void buyService(double money)
(4) mediator.buy(money, this)
(5) mediator.buy(money, this)
九、真题九
1、题目
阅读下列说明和Java代码,将应填入(n)处的字句写在答题纸的对应栏内。
【说明】
某文件管理系统中定义了类OfficeDoe和DocExplorer。当类OfficeDoe发生变化时,类DocExplorer的所有对象都要更新其自身的状态。现采用观察者(Observer) 设计模式来实现该需求,所设计的类图如图6-1所示。
package test_2019_2;
import java.util.*;
interface Observer{
public (1); //填空1
}
interface Subject{
public void Attach(Observer obs);
public void Detach(Observer obs);
public void Notify();
public void setStatus(int staus);
public int getStatus();
}
class OfficeDoc implements Subject{
private List<(2)> myObs;//填空2
private String mySubjectName;
private int m_status;
public OfficeDoc (String name){
mySubjectName=name;
this.myObs=new ArrayList<Observer>();
m_status=0;
}
public void Attach(Observer obs){this.myObs.add(obs);}
public void Detach(Observer obs){this.myObs.remove(obs);}
public void Notify(){
for(Observer obs:this.myObs){
(3);//填空3
}
}
public void setStatus(int status){
m_status=status;
System.out.println("SetStatus Subject["+mySubjectName+"]status:"+status);
}
public int getStatus(){return m_status;}
}
class DocExplorer implements Observer {
private String myObsName;
public DocExplorer(String name, (4) sub) {//填空4
myObsName = name;
sub.(5);//填空5
}
public void update() {
System.out.println("update observer[" + myObsName + "]");
}
}
public class ObserverTest {
public static void main(String[] args) {
System.out.println("Hello Wprld!");
Subject subjectA=new Subject() {
@Override
public void Attach(Observer obs) {
}
@Override
public void Detach(Observer obs) {
}
@Override
public void Notify() {
}
@Override
public void setStatus(int staus) {
}
@Override
public int getStatus() {
return 0;
}
};
Observer observerA = new DocExplorer("observerA",subjectA);
subjectA.setStatus(1);
subjectA.Notify();
}
}
2、解析
本题是对观察者模式的考查,观察者模式的意图是:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
本题根据Observer接口的实现类DocExplorer,实现类包括同名构造函数和update()方法,所以接口Observer缺失的是update()方法,并且没有方法体,(1)空填写void update()。
第2空是myObs表单类型的缺失,根据代码上下文,在构造函数中,根据this.myObs=new ArrayList(),可以知道myObs是Observer表单,第(2)空填写Observer。
第3空是Notify()方法体的缺失,根据代码上下文,Notify传入了一个参数Observer obs,又根据代码上下文可知Observer只有一个update()方法,此时方法体调用的应该是update()方法,调用方法的对应是传入的obs,第(3)空填写obs.update()。
第4空、第5空缺失的是DocExplorer类的同名构造函数传入的参数类型以及构造方法体,这里结合根据观察者模式填空,对于实际观察者类,需要与被观察者联系起来,所以这里是与被观察者Subject联系,也就是调用Subject中的Attach()添加观察者列表。因此第(4)空需要填写参数类型Subject,形参名sub已经给出了提示;sub调用增加观察者方法,将当前观察者添加到对应列表,即第(5)空填写Attach(this)。
3、答案
(1)void update();
(2)Observer;
(3)obs.update();
(4)Subject;
(5)Attach(this);