结构型设计模式
结构设计模式的典型例题!
1. (填空题)【选做】某软件公司欲开发一个多功能文本编辑器,在文本中可以插入图片、动画、视频等多媒体资料,为了节约系统资源,使用享元模式进行设计,类图如下图所示:

在图中,MultimediaFile表示抽象享元,其子类Image、Animation和Video表示具体享元。对于相同的多媒体文件,其大小Size和位置Location可以不同,因此需要通过Setter方法来设置这些外部状态。MultiediaFileFactory是享元工厂,在其中定义一个Hashtable对象作为享元池,存储和维护享元对象。
请完成以下Java代码中空的代码填写,以及执行后的空格填写。
【Java代码】
import java.util.*;
//位置类:外部状态类
class Location{
private int x;
private int y;
public Location(int x,int y){
this.x = x;
this.y = y;
}
//Getter方法和Setter方法省略
}
//大小类:外部状态类
class Size{
private int width;
private int height;
public Size(int width,int height){
this.width = width;
this.height = height;
}
//Getter方法和Setter方法省略
}
//多媒体文件类:抽象享元类
____MultimediaFile{
protected Size size;
protected Location location;
public abstract void display();
public void setSize(Size size){
this.size = size;
}
public void setLocation(Location location){
this.location = location;
}
}
//图片文件类:具体享元类
class Image extends MultimediaFile{
private String fileName;
public Image(String fileName){
this.fileName = fileName;
}
public void display(){
//导入和显示图片文件代码省略,在显示图片时将使用size和location对象
}
}
//动画文件类:具体享元类
class Animation extends MultimediaFile{
//动画文件类代码省略
}
//视频文件类:具体享元类
class Video extends MultimediaFile{
//视频文件类代码省略
}
//多媒体文件工厂类:享元工厂类
class MultimediaFileFactory{
private Hashtable ht;//享元池
private int fileNum = 0;//享元对象计数器
public MultimediaFileFactory(){
ht = ____;
}
//从享元池中获取对象
public ____getMultimediaFile(String fileName){
//根据文件后缀名判断文件类型
String[] strArray = fileName.split("\.");
int ubound = strArray.length;
String extendName = strArray[ubound-1];
if(ht.containsKey(fileName)){
return (MultimediaFile)____;
}else{
if(extendName.equalsIgnoreCase("gif"))||extendName.equalsIgnoreCase("jpg"){
MultimediaFile file = new Image(fileName);
ht.put(fileName,file);
fileNum++;
}else if(extendName.equalsIgnoreCase("swf")){
MultimediaFile file = new Animation(fileName);
ht.put(fileName file);
____;
}
//其他代码省略
}
}
//返回享元对象数量
public int getFileNum(){
return fileNum;
}
}
class Test{
public static void main(String[] args) {
MultimediaFile file1,file2,file3,file4;
MultimediaFileFactory factory;
factory = new MultimediaFileFactory();
file1 = factory.getMultimediaFile("sum.jpg");
file1.setSize(new Size(300,400));
file1.setLocation(new Location(3,5));
file2 = factory.getMultimediaFile("sun.jpg");
file2.setSize(new Size(300,400));
file2.setLocation(new Location(6,5));
file3 = factory.getMultimediaFile("star.swf");
file3.setSize(new Size(200,200));
file3.setLocation(new Location(10,1));
file4 = factory.getMultimediaFile("moon.swf");
file4.setSize(new Size(400,400));
file4.setLocation(new Location(15,2));
System.out.println(file1==file2);//输出语句1
System.out.println(factory.getFileNum());//输出语句2
}
}
在Text类中,“输出语句1”输出结果为____,“输出语句2”输出结果为____。
正确答案:
(1) abstract class
(2) new Hashtable()
(3) MultimediaFile
(4) ht.get(fileName)
(5) fileNum++
(6) true
(7) 3
2. (填空题)现欲实现一个图像浏览系统,要求该系统能够显示BMP、JPEG和GIF三种格式的文件,并且能够在Windows和Linux两种操作系统上运行。系统首先将BMP、JPEG和GIF三种格式的文件解析为像素矩阵,然后将像素矩阵显示在屏幕上。系统必须具有较好的扩展性以支持新的文件格式和操作系统。为满足上述需求并减少所需生成的子类数目,采用桥接设计模式进行设计,所得类图如图所示:

采用该设计模式的原因在于:系统解析BMP、JPEG与GIF文件的代码仅与文件格式相关,而在屏幕上显示像素矩阵的代码仅与操作系统相关。
请完成以下Java代码中空的代码填写。
【Java代码】
class Matrix{ //各种格式的文件最终都被转化为像素矩阵
//此处代码省略
}
interface ImageImp{ //显示像素矩阵m
public void doPaint(Matrix m);
}
class WinImp implements ImageImp{
public void doPaint(Matrix m){/*调用Windows系统的绘制函数绘制像素矩阵*/};
}
class LinuxImp implements ImageImp{
public void doPaint(Matrix m){/*调用Linux系统的绘制函数绘制像素矩阵*/};
}
abstract class Image{
public void setImp(ImageImp imp){
____= imp;
}
public abstract void parseFile(String fileName);
protected ____imp;
}
class BMP extends Image{
public void parseFile(String fileName){
//此处解析BMP文件并获得一个像素矩阵对象m
____; //显示像素矩阵m
}
}
class GIF extends Image{
//此处代码省略
}
class JPEG extends Image{
//此处代码省略
}
public class Main{
public static void main(String[] args) {
//在Windows操作系统上查看demo.bmp图像文件
Image image1 = ____;
ImageImp imageImp1 = ____;
____;
image1.parseFile("demo.bmp");
}
}
现假设该系统需要支持10种格式的图像文件和5种操作系统,不考虑类Matrix和类Main,若采用桥接模式则至少需要设计____个类。
正确答案:
(1) this.imp
(2) ImageImp
(3) imp.doPaint(m)
(4) new BMP()
(5) new WinImp()
(6) image1.setImp(imageImp1)
(7) 17
3. (填空题)某公司的组织结构图如图所示:

现采用组合设计模式来设计,得到如下类图所示:
其中Company为抽象类,定义了在组织结构上添加(Add)和删除(Delete)分公司/办事处或者部门的方法接口。类ConcreteCompany表示具体的分公司或者办事处,分公司或办事处以下可以设置不同的部门。类HRDepartment和FinanceDepartment分别表示人力资源部和账务部。
请完成以下Java代码中空的代码填写。
【Java代码】
import java.util.*;
____Company{
protected String name;
public Company(String name){
____= name;
}
public abstract void Add(Company c); //增加子公司、办事处或部门
public abstract void Delete(Company c); //增加子公司、办事处或部门
}
class ConcreteCompay extends Company{
private List<____> children = new ArrayList<____>();
//存储子公司、办事处或部门
public ConcreteCompay(String name){
super(name);
}
public void Add(Company c){____.add(c);}
public void Delete(Company c){____.remove(c);}
}
class HRDepartment extends Company{
public HRDepartment(String name){
super(name);
//其他代码省略
}
}
class FinanceDepartment extends Company{
public FinanceDepartment(String name){
super(name);
//其他代码省略
}
}
public class Test{
public static void main(String[] args) {
ConcreteCompay root = new ConcreteCompay("北京总公司");
root.Add(new HRDepartment("总公司人力资源部"));
root.Add(new FinanceDepartment("总公司财务部"));
ConcreteCompay comp = new ConcreteCompay("上海分公司");
comp.Add(new HRDepartment("上海分公司人力资源部"));
comp.Add(new FinanceDepartment("上海分公司财务部"));
____;
ConcreteCompay comp1 = new ConcreteCompay("南京办事处");
comp1.Add(new HRDepartment("南京办事处人力资源部"));
comp1.Add(new FinanceDepartment("南京办事处财务部"));
____; //其他代码省略
}
}
正确答案:
(1) abstract class
(2) this.name
(3) Company
(4) Company
(5) children
(6) children
(7) root.Add(comp)
(8) comp.Add(comp1)
4. (填空题)某公司欲开发一套手机来电提示程序,在最简单的版本中,手机在接收到来电时会发出声音来提醒用户;在振动版本中,除了声音外,在来电时手机还能产生振动;在更高级的版本中,手机不仅能够发声和产生振动,而且还会有灯光闪烁提示。现使用装饰设计模式设计该软件,所得类图如下所示:

其中Cellphone为抽象类,声明了来电方法receiveCall(),SimplePhone为简单手机类,提供了声音提示,JarPhone和ComplexPhone分别提供了振动提示和灯光闪烁提示。PhoneDecorator是抽象装饰者,它维持一个对父类对象的引用。
请完成以下Java代码中空的代码填写。
【Java代码】
abstract class Cellphone{
public abstract void receiveCall();
}
class SimplePhone extends Cellphone{
public void receiveCall(){
System.out.println("声音提示");
}
}
class PhoneDecorator extends Cellphone{
private ____phone = null;
public PhoneDecorator(Cellphone phone){
if (phone != null){
____;
}else {
this.phone = new SimplePhone();
}
}
public void receiveCall(){
____;
}
}
class JarPhone extends PhoneDecorator{
public JarPhone(Cellphone phone){
____;
}
public void receiveCall(){
super.receiveCall();
System.out.println("振动提示");
}
}
class ComplexPhone extends PhoneDecorator{
public ComplexPhone(Cellphone phone){
____;
}
public void receiveCall(){
super.receiveCall();
System.out.println("灯光闪烁提示");
}
}
class Client{
public static void main(String a[]){
Cellphone p1 = new ____; //创建具有声音提示的手机
p1.receiveCall();
Cellphone P2 = new ____; //创建具有声音提示和振动提示的手机
p2.receiveCall();
Cellphone p3 = new ____;
//创建具有声音提示、振动提示和灯光提示的手机
p3.receiveCall();
}
}
正确答案:
(1) Cellphone
(2) this.phone = phone
(3) phone.receiveCall()
(4) super(phone)
(5) super(phone)
(6) SimpliPhone()
(7) JarPhone(p1)
(8) ComplexPhone(p2)
5. (填空题)某信息系统需要提供一个数据读取和报表显示模块,可以将来自不同类型文件中的数据转换成XML格式,并对数据进行统计和分析,然后以报表方式来显示数据。由于该过程需要涉及多个类,因此使用外观模式进行设计,所得类图如下所示:

在上图中,FileOperation类用于读取文件、XMLDataConvertor类用于将不同格式的文件转换为XML格式、DataAnalysis类用于对XML数据进行统计分析、ReportDisplay类用于显示报表。为了让系统具有更好的扩展性,在系统设计中引入了抽象外观类AbstractFacade,它拥有多个不 的子类,如XMLFacade,它用于与读取、分析和显示XML数据的类交互,ExtendedFacade类用于读取、转换、分析和显示非XML数据的类交互。
请完成以下Java代码中空填写。
【Java代码】
class FileOperation{
public String read(String fileName){
//读取文件代码省略
}
}
class XMLDataConvertor{
public String convert(String fileStr){
//文件格式转换代码省略
}
}
class DataAnalysis{
public String handle(String xmlStr){
//数据分析统计代码省略
}
}
class ReportDisplay{
public void display(String xmlStr){
//报表显示代码省略
}
}
____AbstractFacade{
public abstract void execute(String fileName);
}
class XMLFacade extends AbstractFacade{
private FileOperation fo;
private DataAnalysis da;
private ReportDisplay rd;
public XMLFacade(){
fo = new FileOperation();
da = new DataAnalysis();
rd = new ReportDisplay();
}
public void execute(String fileName){
String str = ____;//读取文件
String strResult = ____;//分析数据
____;//显示报表
}
}
class ExtendedFacade extends AbstractFacade{
private FileOperation fo;
private XMLDataConvertor dc;
private DataAnalysis da;
private ReportDisplay rd;
public ExtendedFacade(){
fo = new FileOperation();
dc = new XMLDataConvertor();
da = new DataAnalysis();
rd = new ReportDisplay();
}
public void execute(String fileName){
String str = ____;//读取文件
String strXml = ____;//转换文件
String strResult = ____;//分析数据
____;//显示报表
}
}
class Test{
public static void main(String[] args) {
AbstractFacade facade;
facade = ____;
facade.execute("file.xml");
}
}
正确答案:
(1) abstract class
(2) fo.read(fileName)
(3) da.handle(str)
(4) rd.display(strResult)
(5) fo.read(fileName)
(6) dc.convert(str)
(7) da.handle(strXml)
(8) rd.display(strResult)
(9) new XMLFacade()
6. (填空题)某公司欲开发一款儿童玩具汽车,为了更好的吸引小朋友的注意力,该玩具汽车在移动过程中伴随着灯光闪烁和声音提示,在该公司以往的产品中已经实现了控制灯光闪烁和声音提示的程序,为了重用先前的代码并且使得汽车控制软件具有更好的灵活性和扩展性,使用适配器模式设计该系统,所得类图如下所示:

在图中,CarController类是汽车控制器,它包括三个方法用于控制汽车的行为,其中move()用于控制汽车的移动,sound()用于控制汽车的声音,light()用于控制汽车灯光的闪烁,sound()和light()是抽象方法。Sound类是抽象声音类,其方法phonate()用于实现声音提示,在其子类ConcreteSound中实现了该方法;Lamp类是灯光类,其方法twinkle()用于实现灯光闪烁,在其子类ConcreteLamp中实现了该方法。CarAdapter充当适配器,它通过分别调用Sound类的phonate()方法和Lamp类的twinkle()方法实现声音播放和灯光闪烁。
请完成以下Java代码中空的代码填写,以及执行后的空白填写。
【Java代码】
abstract class Sound{ //抽象声音类
public abstract void phonate();
}
class ConcreteSound extends Sound{ //具体声音类
public void phonate(){
System.out.println("声音播放!");
}
}
abstract class Lamp{ //抽象灯光类
public abstract void twinkle();
}
class ConcreteLamp extends Lamp{ //具体灯光类
public void twinkle(){
System.out.println("灯光闪烁!");
}
}
____Carcontroller{ //汽车控制器
public void move(){
System.out.println("汽车移动!");
}
public abstract void sound();
public abstract void light();
}
class CarAdapter ____{ //汽车适配器
private Sound sound;
private Lamp lamp;
public CarAdapter(Sound sound,Lamp lamp){
____;
____;
}
public void sound(){
____;
}
public void light(){
____;
}
}
class Client{
public static void main(String args[]){
Sound sound;
Lamp lamp;
CarController car;
sound = new ConcreteSound();
lamp = new ConcreteLamp();
car = ____;
car.move();
car.sound();
car.light();
}
}
在本实例中,使用了____(填写类适配器或对象适配器)模式。
正确答案:
(1) abstract
(2) extends CarController
(3) this.sound = sound
(4) this.lamp = lamp
(5) sound.phonate()
(6) lamp.twinkle()
(7) new CarAdapter(sound,lamp)
(8) 对象适配器
7. (填空题)某信息咨询公司推出收费的在线商业信息查询模块,需要对查询用户进行身份验证并记录查询日志,以便根据查询次数收取查询费用,现使用代理模式设计该系统,所得类图如下所示:

在图中,AccessValidator类用于验证用户身份,它提供方法validate()来实现身份验证;Logger类用于记录用户查询日志,它提供方法log()来保存日志;RealSearcher类实现查询功能,它提供方法doSearch()来查询信息。ProxySearcher作为查询代理,维持对RealSearcher对象、AccessValidator对象和Logger对象的引用。
请完成以下Java代码中空的代码填写。
【Java代码】
class AccessValidator{
public boolean validate(String userId){
//身份验证实现代码省略
}
}
class Logger{
public void log(String userId){
//日志记录实现代码省略
}
}
interface Searcher{
public String doSearch(String userId,String keyword);
}
class RealSearcher implements Searcher{
public String doSearch(String userId,String keyword){
//信息查询实现代码省略
}
}
class ProxySearcher ____{
private RealSearcher searcher = new RealSearcher();
private AccessValidator validator;
private Logger logger;
public String doSearch(String userId,String Keyword){
//如果身份验证成功,则执行查询
if(____){
String result = searcher.doSearch(userId,keyword);
____;//记录查询日志
____;//返回查询结果
}else{
return null;
}
}
public bollean validate(String userId){
validator = new AccessValidator();
____;
}
public void log(String userId){
logger = new Logger();
____;
}
}
class Test{
public static void main(String[] args) {
____;//针对抽象编程,客户端无须分辩真实主题类和代理类
searcher = new ProxySearcher();
String result = searcher.doSearch("Sunny","Money");
//此处省略后续处理代码
}
}
正确答案:
(1) implements Searcher
(2) validate(userId)
(3) log(userId)
(4) return result
(5) return validator.validate(userId)
(6) logger.log(userId)
(7) Searcher searcher
更多推荐


所有评论(0)