一. 单选题(共4题)

  1. (单选题)某公司欲开发一个图形控件库,要求可以在该图形控件库中方便地增加新的控件,而且可以动态地改变控件的外观或给控件增加新的行为,如可以为控件增加复杂的立体边框、增加控件的鼠标拖拽行为等。针对上述需求,使用( )模式来进行设计最合适。 A. 适配器 (Adapter) B. 装饰 (Decorator) C. 外观 (Facade) D. 命令 (Command) 我的答案: B:装饰 (Decorator);正确答案: B:装饰 (Decorator);

  1. (单选题)下图是( )模式的类图。 image.png

A. 桥接 (Bridge) B. 工厂方法 (Factory Method) C. 模板方法 (Template Method) D. 外观 (Facade) 我的答案: D:外观 (Facade);正确答案: D:外观 (Facade);


  1. (单选题)以下( )不是装饰模式的适用条件。 A. 要扩展一个类的功能或给一个类增加附加责任 B. 要动态地给一个对象增加功能,这些功能还可以动态撤销 C. 要动态组合多于一个的抽象化角色和实现化角色 D. 要通过一些基本功能的组合而产生复杂功能,而不使用继承关系 我的答案: C:要动态组合多于一个的抽象化角色和实现化角色;正确答案: C:要动态组合多于一个的抽象化角色和实现化角色;

  1. (单选题)以下关于外观模式的叙述错误的是( )。 A. 外观模式要求一个子系统的外部与其内部的通信必须通过一个统一的外观对象进行 B. 在增加外观对象之后,客户类只需要直接和外观对象交互即可,子系统类间的复杂关系由外观类来实现,降低了系统的耦合度 C. 外观模式可以很好地限制客户使用子系统类,对客户访问子系统类做限制可以提高系统的灵活性 D. 可以为一个系统提供多个外观类 我的答案: C:外观模式可以很好地限制客户使用子系统类,对客户访问子系统类做限制可以提高系统的灵活性;正确答案: C:外观模式可以很好地限制客户使用子系统类,对客户访问子系统类做限制可以提高系统的灵活性;

二. 多选题(共2题)

  1. (多选题)以下属于外观模式的应用实例是( )。 A. B/S系统中的首页 B. C/S系统中的菜单 C. 在分层结构中,层与层之间增加一个入口 D. JDBC驱动程序 我的答案: ABCD:B/S系统中的首页; C/S系统中的菜单; 在分层结构中,层与层之间增加一个入口; JDBC驱动程序;正确答案: ABC:B/S系统中的首页; C/S系统中的菜单; 在分层结构中,层与层之间增加一个入口;

  1. (多选题)以下关于装饰模式描述正确的是( )。 A. 在透明装饰模式中要求客户端完全针对抽象构件类编程,具体装饰类新增的行为不能单独调用。 B. 在半透明装饰模式的客户端中具体构件类型无须关心,是透明的,但是具体装饰类型必须指定,是不透明的。 C. Java I/O中的输入流和输出流的设计运用了装饰模式 D. Java.swing包中的一些图形界面构件功能的增强运用了装饰模式 我的答案: ABCD:在透明装饰模式中要求客户端完全针对抽象构件类编程,具体装饰类新增的行为不能单独调用。; 在半透明装饰模式的客户端中具体构件类型无须关心,是透明的,但是具体装饰类型必须指定,是不透明的。; Java I/O中的输入流和输出流的设计运用了装饰模式; Java.swing包中的一些图形界面构件功能的增强运用了装饰模式;正确答案: ABCD:在透明装饰模式中要求客户端完全针对抽象构件类编程,具体装饰类新增的行为不能单独调用。; 在半透明装饰模式的客户端中具体构件类型无须关心,是透明的,但是具体装饰类型必须指定,是不透明的。; Java I/O中的输入流和输出流的设计运用了装饰模式; Java.swing包中的一些图形界面构件功能的增强运用了装饰模式;

三. 填空题(共2题)

  1. 某公司欲开发一套手机来电提示程序,在最简单的版本中,手机在接收到来电时会发出声音来提醒用户;在振动版本中,除了声音外,在来电时手机还能产生振动;在更高级的版本中手机不仅能够发声和产生振动,而且还会有灯光闪烁提示。现采用装饰设计模式来设计,得到如图1所示的类图。 image.png 其中Cellphone为抽象类,声明了来电方法receiveCall(),SimplePhone为简单手机类,提供了声音提示,JarPhone和ComplexPhone分别提供了振动提示和灯光闪烁提示。PhoneDecorator是抽象装饰者,它维持一个对父类对象的引用。
【Java代码】
abstract class Cellphone
{  public abstract void receiveCall();  }

class SimplePhone extends Cellphone
{
 public void receiveCall()
 {  System.out.println("声音提示");  }
}


class PhoneDecorator extends Cellphone
{
 private      (1)       phone=null;
 public PhoneDecorator(Cellphone phone)
 {
 if(phone!=null)
 {         (2)        ;  }
 else
 {  this.phone=new SimplePhone();  }
 }
 public void receiveCall()
 {         (3)        ;  }
}

class JarPhone extends PhoneDecorator
{
 public JarPhone(Cellphone phone)
 {         (4)        ;  }
 public void receiveCall()
 {
 super.receiveCall();
 System.out.println("振动提示"); 
 }
}

class ComplexPhone extends PhoneDecorator
{
 public ComplexPhone(Cellphone phone)
 {         (5)        ;  }
 public void receiveCall()
 {
 super.receiveCall();
 System.out.println("灯光闪烁提示"); 
 }
}

class Client
{
 public static void main(String a[])
 {
 Cellphone p1=new        (6)        ;  //创建具有声音提示的手机
 p1.receiveCall();
 Cellphone p2=new        (7)        ;  //创建具有声音提示和振动提示的手机
 p2.receiveCall();
 Cellphone p3=new         (8)        ;  //创建具有声音提示、振动提示和灯光提示的手机
 p3.receiveCall();
 }
}

正确答案: (1) Cellphone (2) this.phone = phone (3) phone.receiveCall() (4) super(phone) (5) super(phone) (6) SimplePhone() (7) JarPhone(p1) (8) ComplexPhone(p2)


  1. (填空题)某信息系统需要提供一个数据读取和报表显示模块,可以将来自不同类型文件中的数据转换成XML格式,并对数据进行统计和分析,然后以报表方式来显示数据。由于该过程需要涉及到多个类,因此使用外观模式进行设计,其类图如图1所示: image.png 在图1中,FileOperation类用于读取文件、XMLDataConvertor类用于将不同格式的文件转换为XML格式、DataAnalysis类用于对XML数据进行统计分析、ReportDisplay类用于显示报表。为了让系统具有更好的扩展性,在系统设计中引入了抽象外观类AbstractFacade,它拥有多个不同的子类,如XMLFacade,它用于与读取、分析和显示XML数据的类交互,ExtendedFacade类用于与读取、转换、分析和显示非XML数据的类交互。
【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)
 {  //报表显示代码省略  }
}

 abstract class 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 =         (1)         ; //读取文件
 String strResult =         (2)         ; //分析数据
         (3)         ; //显示报表
 }
}

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 =         (4)         ; //读取文件
 String strXml =         (5)         ; //转换文件
 String strResult =         (6)         ; //分析数据
         (7)         ; //显示报表
 }
}

class Test
{
 public static void main(String args[])
 {
 AbstractFacade facade;
 facade =         (8)         ;
 facade.execute("file.xml");
 }
}

正确答案: (1) fo.read(fileName) (2) da.handle(str) (3)rd.display(strResult) (4) fo.read(fileName) (5) dc.convert(str) (6) da.handle(strXml) (7) rd.display(strResult) (8) new XMLFacade()


四. 判断题(共2题)

  1. (判断题, 1分)外观模式是迪米特法则的一种具体实现 A. 对 B. 错 我的答案: 对正确答案: 对

  1. (判断题, 1分)透明装饰模式可以对一个已装饰过的对象进行多次装饰,而半透明装饰模式不能对同一对象多次装饰。 A. 对 B. 错 我的答案: 对正确答案: 对

五. 简答题(共2题)

  1. (简答题)某小吃店出售杂粮煎饼,顾客可以根据自己的喜好在煎饼中添加各种配料。小店出售的煎饼每块5元,配料的种类及价格如下表所示。 image.png 现使用装饰模式为该小店设计一个程序实现计算费用的功能,输出每份煎饼的组成描述及花费 (如某顾客买了一块煎饼,在煎饼中放了一个鸡蛋,一份生菜和一根火腿肠)。

(1)画出UML类图 image.png (2)用Java语言编程实现

public class Client {

    public static void main(String[] args) {

        Pancake pancake=new MakePancake();

        Pancake pancake1=new Egg(pancake);

        Pancake pancake2=new Romaine(pancake1);

        Pancake pancake3=new Ham(pancake2);

        Pancake pancake4=new Chicken(pancake3);

        System.out.println(pancake4.getDescription());

        System.out.println(pancake4.getCost());

    }

}

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

public abstract class Pancake{

    public abstract String getDescription();

    public abstract int getCost();

}

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

public class CondimentDecorator extends Pancake{
   private Pancake pancake;

   public CondimentDecorator(Pancake pancake) {
       this.pancake = pancake;
   }
   @Override
   public String getDescription() {
       return pancake.getDescription();
   }
   @Override
   public int getCost() {
       return pancake.getCost();
   }
}

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

public class MakePancake extends Pancake{

    @Override

    public String getDescription() {

        return "制作一份煎饼";

    }

    @Override

    public int getCost() {

        return 5;

    }

}

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

public class Egg extends CondimentDecorator{

    public Egg(Pancake pancake) {

        super(pancake);

    }

    @Override

    public String getDescription(){

        return super.getDescription() + this.addEgg();

    }

    @Override

    public int getCost(){

        return super.getCost()+this.addEggCost();

    }

    public String addEgg(){

        return "加鸡蛋";

    }

    public int addEggCost(){

        return 2;

    }

}

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

public class Romaine extends CondimentDecorator{
   public Romaine(Pancake pancake) {
       super(pancake);
   }
   @Override
   public String getDescription(){
       return super.getDescription() + this.addRomaine();
   }
   @Override
   public int getCost(){
       return super.getCost()+this.addRomaineCost();
   }
   public String addRomaine(){
       return "加生菜";
   }
   public int addRomaineCost(){
       return 1;
   }
}

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

public class Ham extends CondimentDecorator{
   public Ham(Pancake pancake) {
       super(pancake);
   }
   @Override
   public String getDescription(){
       return super.getDescription() + this.addHam();
   }
   @Override
   public int getCost(){
       return super.getCost()+this.addHamCost();
   }
   public String addHam(){
       return "加火腿";
   }
   public int addHamCost(){
       return 3;
   }
}

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

public class Chicken extends CondimentDecorator{
   public Chicken(Pancake pancake) {
       super(pancake);
   }
   @Override
   public String getDescription(){
       return super.getDescription() + this.addChicken();
   }
   @Override
   public int getCost(){
       return super.getCost()+this.addChickenCost();
   }
   public String addChicken(){
       return "加鸡肉";
   }
   public int addChickenCost(){
       return 4;
   }
}

3、效果展示 image.png


  1. (简答题)某系统需要提供一个文件加密模块,加密流程包括三个操作,分别是读取源文件、加密、保存加密之后的文件。读取文件和保存文件使用流来实现,这三个操作相对独立,其业务代码封装在三个不同的类中。现在需要提供一个统一的加密外观类,用户可以直接使用该加密外观类完成文件的读取、加密和保存三个操作,而不需要与每一个类进行交互,使用外观模式设计该加密模块。。

1、绘制UML类图 image.png 2、使用Java语言编程模拟实现

public class Client {
   public static void main(String args[]) {
       EncryptFacade ef=new EncryptFacade();
       try {
           ef.fileEncrypt("E:/外观模式/1.txt","E:/外观模式/2.txt");
       } catch (Exception e) {
           e.printStackTrace();
       }
   }
}

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

public class EncryptFacade {
   private FileReader reader;
   private CipherMachine cipher;
   private FileWriter writer;

   public EncryptFacade() {
       reader=new FileReader();
       cipher=new CipherMachine();
       writer=new FileWriter();
   }
   public void fileEncrypt(String fileNameSrc,String fileNameDes) throws Exception {
       String plainStr=reader.read(fileNameSrc);
       if(plainStr!=null){
           String encryptStr=cipher.encrypt(plainStr);
           writer.write(encryptStr, fileNameDes);
       }
   }
}

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

import java.io.File;

public class FileReader {
   public String read(String fileNameSrc) {
       File file = new File(fileNameSrc);
       String path = file.getPath();
       if(!file.exists()){
           System.out.println("源文件不存在");
           return null;
       }
       System.out.println("读取源文件...");
       return path;
   }
}
===============================================

import java.io.*;

public class CipherMachine {
   public String encrypt(String path) throws Exception {
       System.out.println("文件加密...");
       InputStream in = new FileInputStream(path);
       byte[] buffer = new byte[1024];
       int r;
       byte[] buffer2=new byte[1024];
       while (( r= in.read(buffer)) > 0) {
           for(int i=0;i<r;i++) {
               byte b=buffer[i];
               buffer2[i]=b==255?0:++b;
           }
       }
       in.close();
       return buffer2.toString();
   }
}

===============================================
import java.io.*;

public class FileWriter {
   public void write(String encryptStr,String destFile) throws Exception {
       System.out.println("写入文件...");
       byte[] buffer=encryptStr.getBytes();
       File dest = new File(destFile);
       OutputStream out = new FileOutputStream(destFile);
       out.write(buffer, 0, buffer.length);
       out.flush();
       dest.renameTo(new File(destFile));
       out.close();
   }
}

3、效果展示 image.png 源文件 image.png 加密文件 image.png