单选题
1.采用面向对象方法设计的应用程序的特点是:可复用性更强。
2.面向对象方法中类的设计不包括:代码的组织与表示。
包括:类的组织与表示,行为的组织与表示,属性的组织与表示。
3.下列关于面向对象和设计模式的描述中,错误的是:一个设计良好的面向对象应用程序应具有低内聚、高耦合的特点。
正确的是:
A:面向对象方法中类设计的难点在于变化的存在,例如职责的变化、实现的变化等。
B:设计模式代表了最佳的实践,提供了软件开发过程中面临的一般问题的解决方案。
C:设计模式方便开发人员之间沟通和交流,使得设计方案更加通俗易懂。
4.面向对象设计应支持变化,下列相关描述中,不正确的是:建议通过修改既有代码来适应变化。
正确的是:
A:一个不考虑系统变化的设计有可能需要重新设计,重新设计的代价往往是巨大的。
B:通过显式地指定一个类来创建对象是导致重新设计的原因之一。
C:不能方便地对类进行修改是导致重新设计的原因之一。
5.下列选项中最适合用依赖关系描述的是:工厂和产品。
6.在一个课程注册系统中,定义了类CourseSchedule和类Course,其中类CourseSchedule中定义了方法add(Course c)和方法remove(Course c),则这两个类之间的关系最可能是:依赖关系。
7.如果类A仅在其成员函数fun中定义并使用了类B的一个对象,类A其他部分的代码都不涉及类B,那么类A与类B的关系最可能是:依赖。
8.下列代码中, 体现“knows a” 关系的是:class B { A * mpA };。
9.下列哪种用法体现出的类A和类B之间的耦合关系最强:类A保护继承类B。
10.下列选项中属于面向对象设计原则的是: 里氏替换。
11.Open-Close原则的含义是一个软件实体:应当对扩展开放,对修改关闭。
12.下列关于开闭原则的描述中,不正确的是:面向接口进行软件设计,可以很容易地构建100%满足开闭原则的软件系统。
正确的是:
A:开闭原则的英文名称是The Open-Closed Principle,简称OCP。
B:开闭原则要求软件实体(模块,类,方法等)应该对扩展开放,对修改关闭。
C:开闭原则强调接口是稳定的,可复用的,但接口的实现是可变的。
13.下列关于单一职责原则的描述中,不正确的是:单一职责原则提高了类之间的耦合性。
正确的是:
A:单一职责原则的英文名称是Single Responsibility Principle,简称SRP。
B:单一职责要求一个类应该只有一个职责。
C:单一职责原则有利于对象的稳定,能降低类的复杂性。
14.在面向对象设计原则中,哪个原则表示高层模块不应该依赖于低层模块,都应该依赖于抽象,抽象不应该依赖于细节,细节应该依赖于抽象:依赖倒置原则。
15.依赖倒置原则就是要依赖于(抽象),而不要依赖于实现;或者说要针对接口编程,不要针对实现编程。
16.下列关于面向对象复用的描述中,不正确的是:通过生成子类的复用称为黑箱复用,通过组装或组合对象的复用称为白箱复用。
正确的是:
A:针对接口编程,而不是针对实现编程。
B:面向对象系统中功能复用的两种最常用技术是类继承和对象组合。
C:优先使用组合,而不是继承。
17.下列关于面向对象设计基本原则的描述中,错误的是:高层模块应该依赖于低层模块。
正确的是:
A:所有引用基类对象的地方必须能透明地使用其公有派生类的对象。
B:永远不要让一个类存在多个改变的理由。
C:使用多个专门的接口比使用单一的总接口要好。
18.以设计复用为目的,采用一种良好定义、正规的、一致的方式记录的软件设计经验的是:设计模式。
19.下列关于设计模式的描述中,正确的是:使用设计模式能提高软件开发效率。
20.下列关于设计模式的描述中,不正确的是:理论上,设计模式一定是最优秀的解决方案。
正确的是:
A:设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
B:使用设计模式能方便开发人员之间的沟通和交流。
C:使用设计模式能复用成功的设计,避免那些导致不可重用的设计方案。
21.设计模式的两大主题是:系统复用与系统扩展。
22.设计模式具有的优点是:提升软件设计的质量。
23.设计模式不能解决下列哪个问题:确定软件功能都正确实现。
能够解决:
A:针对接口编程。
B:增强软件扩展性和灵活性。
C:适应需求变化。
24.设计模式的关键要素不包括:目的。
包括:
A:名称。
B:解决方案。
C:效果。
25.下列关于创建型模式的描述中,错误的是:创建型模式中客户程序必须知道要创建对象的所属具体类。
正确的是:
A:创建型模式关注的是对象的创建。
B:创建型模式分离了对象创建和对象使用。
C:创建型模式隐藏了对象实例是如何被创建和组织的。
26.在简单工厂模式中,如果需要增加新的具体产品,通常需要修改(工厂类)的源代码。
27.以下关于工厂方法模式的叙述,错误的是:工厂方法模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态,工厂方法模式退化后可以演变成抽象工厂模式。
正确的是:
A:在工厂方法模式中引入了抽象工厂类,而具体产品的创建延迟到具体工厂中实现。
B:工厂方法模式添加新的产品对象很容易,无须对原有系统进行修改,符合开闭原则。
C:工厂方法模式存在的问题是在添加新产品时需要编写新的产品类,而且还要提供与之对应的具体工厂类,随着类个数的增加会给系统带来一些额外开销。
28.下列关于工厂方法模式的描述中,不正确的是:工厂方法模式是对象创建型模式。
正确的是:
A:工厂方法模式允许系统在不修改已有工厂类的情况下引进新产品。
B:工厂方法模式将产品类的实例化操作延迟到工厂子类中完成。
C:工厂方法模式符合开闭原则。
29.某银行系统采用工厂模式描述其不同账户之间的关系,设计出的类图如下所示。其中与工厂模式中的工厂角色、产品角色相对应的类分别是:Bank,Account。
+-------------------+
| Bank |
|-------------------|
| + createAccount() |
+-------------------+
|
|
Holds
|
v
+-------------------+
| Account {abstract}|
|-------------------|
| |
+-------------------+
^ ^
| |
+-------------------+ +-------------------+
| Checking | | Savings |
|-------------------| |-------------------|
| | | |
+-------------------+ +-------------------+
+-------------------+
| Client |
|-------------------|
| |
+-------------------+
30.提供一个创建一系列相关或相互依赖对象的接口的是:抽象工厂模式。
31.下图描述的是那种模式:抽象工厂模式。
+-------------------+
| Mouse |
|-------------------|
| + sayHi() |
+-------------------+
^
|
+-------------------+ +-------------------+ +-------------------+
| DellMouse | | HpMouse | | AsusMouse |
|-------------------| |-------------------| |-------------------|
| + sayHi() | | + sayHi() | | + sayHi() |
| "DellMouse" | | "HpMouse" | | "AsusMouse" |
+-------------------+ +-------------------+ +-------------------+
+-------------------+
| Keybo |
|-------------------|
| + sayHi() |
+-------------------+
^
|
+-------------------+ +-------------------+ +-------------------+
| DellKeybo | | HpKeybo | | AsusKeybo |
|-------------------| |-------------------| |-------------------|
| + sayHi() | | + sayHi() | | + sayHi() |
| "DellKeybo" | | "HpKeybo" | | "AsusKeybo" |
+-------------------+ +-------------------+ +-------------------+
+-------------------+
| PcFactory |
|-------------------|
| + createMouse() |
| + createKeybo() |
+-------------------+
^
|
+-------------------+ +-------------------+ +-------------------+
| DellFactory | | HpFactory | | AsusFactory |
|-------------------| |-------------------| |-------------------|
| + createMouse() | | + createMouse() | | + createMouse() |
| return DellMouse| | return HpMouse | | return AsusMouse|
| + createKeybo() | | + createKeybo() | | + createKeybo() |
| return DellKeybo| | return HpKeybo | | return AsusKeybo|
+-------------------+ +-------------------+ +-------------------+
32.小明正在设计一款音视频播放软件,该软件要能支持界面主题的更换,即界面中的按钮、字体、背景等一起随界面主题的改变而变化。针对上述需求,采用哪个设计模式最为合适:抽象工厂模式。
33.某公司要开发一个图表显示系统,在该系统中曲线图生成器可以创建曲线图、曲线图图例和曲线图数据标签,柱状图生成器可以创建柱状图、柱状图图例和柱状图数据标签。用户要求可以很方便地增加新类型的图形,系统需具备良好的可扩展能力。针对这种需求,公司采用(抽象工厂模式)最为恰当。
34.游戏不同场景中的房屋都由五个部分组成:地板、墙壁、窗户、门和天花板,构建房屋的步骤固定,而具体组件(门、窗等)易变。针对上述房屋,采用哪个设计模式最为合适:建造者。
35.开发一个自动生成公文的程序,公文的基本内容包括标题、主送单位、正文、发文单位、日期及签发人等,程序应支持频繁地创建相似公文对象。采用哪个设计模式最为合适:原型。
36.某公司要开发一个即时聊天软件,用户在聊天过程中可以与多位好友同时聊天,在私聊时将产生多个聊天窗口,为了提高聊天窗口的创建效率,要求根据第一个窗口快速创建其他窗口。针对这种需求,采用(原型模式)进行设计最为合适。
37.限制类的实例对象只能有一个的是:单例模式。
38.下列关于单例模式的描述中,不正确的是:单例类可以派生子类,易于扩展。
正确的是:
A:单例类只能有一个实例。
B:单例类应提供一个访问它的全局访问点。
C:单例类的Instance方法是静态的。
39.某软件系统需要从指定的XML文件读取较多的配置参数,作为全局共享资源,方便系统初始化及运行过程中使用。针对上述场景,哪个设计模式最为合适:单例。
40.将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作的是:适配器模式。
41.下列关于适配器模式的描述中,不正确的是:同一个适配器可以把适配者类和它的子类都适配到目标接口。
正确的是:
A:适配器模式可以将一个接口转换成客户希望的另一个接口。
B:适配器模式中目标类(Target)可以是一个抽象类或接口,也可以是具体类。
C:适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
42.在对象适配器中,适配器类(Adapter)和适配者类(Adaptee)之间的关系为:关联关系。
43.现在需要开发一个文件转换软件,将文件由一种格式转换成另一种格式,例如将XML文件转换成PDF文件,将DOC文件转换成TXT文件,有些文件格式转换代码已经存在,为了将已有的代码应用于新软件而不需要修改软件的整体结构,可以使用:适配器模式。
44.用于分离接口和具体实现,使得接口和实现可独立变化的是:桥接模式。
45.桥接模式的本质是:分离抽象和实现。
46.轿车可按品牌分,如红旗、奔腾、中华等,也可按变速方式来分,如手动、自动等,还可按驱动方式来分,如前驱、后驱、四驱等。针对上述轿车,采用哪个设计模式最为合适:桥接模式。
47.小明正在设计一个银行业务系统,该系统对于日志记录有如下要求:按格式分类需记录操作日志、 交易日志、 异常日志等; 按照距离分类分为在本地记录日志和在异地记录日志等。针对上述需求,采用哪个模式能够方便地记录各种日志:桥接模式。
48.可以用来描述树形结构的是:组合模式。
49.为了使客户端以一致的方式处理树形结构中的叶子节点和容器节点,实现客户端的透明操作,组合模式中引入了:抽象构件类。
50.用于为一个对象添加更多功能而不使用子类的是:装饰模式。
51.下列关于外观模式的描述中,不正确的是:外观模式是迪米特原则的一种具体实现,同时也完全符合开闭原则。
52.下列哪个模式是迪米特原则的典型应用:外观模式。
53.小明正在维护一个遗留的大型系统,该系统设计粗糙且遗留代码高度复杂,但新需求的开发却必须依赖于它所包含的一些功能,针对上述需求,采用哪个设计模式最为合适:外观模式。
54.设计一个模块M,为系统中其他模块提供访问不同数据库的通用接口,这些数据库的访问接口有一定的差异,但访问过程相同,例如,先连接数据库,再打开数据库,最后对数据库进行查询。针对上述模块M,采用哪个设计模式最为合适:外观模式。
55.在构建一个层次结构的系统时,可以使用下列哪个模式来定义系统中每层的入口点:外观模式。
56.小明要编写一个鼠标单击点破泡泡的解压小游戏,假设共有66个泡泡,每个泡泡的大小都一样,颜色随机,但一定是5种指定颜色中的1种,位置随机,那么设计泡泡时最适合使用:享元模式。
57.下列关于代理模式的描述中,不正确的是:代理模式中客户端需要知道真实主题(RealSubject)对象。
58.代理模式的本质是:控制对象访问。
59.计算机使用者一般会在Windows系统桌面上设置常用软件的快捷方式,以快速方便地启动软件。针对上述场景,哪个设计模式最为合适:代理模式。
60.下列关于职责链模式的描述中,不正确的是:发出这个请求的客户端知道链上的哪一个处理者最终处理了这个请求。
正确的是:
A:职责链模式可以避免请求发送者与处理者耦合在一起。
B:职责链模式可以将请求的处理者组织成一条链,并让请求沿着链传递。
C:系统可以动态地重新组织链和分配责任。
61.下列关于命令模式的描述中,不正确的是:宏命令是命令模式和装饰模式联用的产物。
正确的是:
A:命令模式又称为动作(Action)模式或事务(Transaction)模式。
B:命令模式对请求进行封装,将发出请求的职责和执行请求的职责分隔开。
C:命令模式可能会导致某些系统有过多的具体命令类。
62.Web开发人员对Web服务器管理的所有Web资源:例如JSP,Servlet,静态图片文件或静态HTML文件等进行拦截,从而实现一些特殊的功能,例如实现URL级别的权限访问控制,过滤敏感词汇,压缩响应信息等,针对上述需求,采用哪个模式最为合适:职责链模式。
63.体现“集中管理多个对象间的交互过程和顺序”的是:中介者模式。
64.下列关于中介者模式的描述中,不正确的是:中介者模式用中介者和同事的多对多交互代替了原来同事之间的一对多交互。
正确的是:
A:中介者通过封装交互,使得各同事对象不再需要显式地相互引用,从而使其耦合松散。
B:中介者和外观模式都是迪米特法则的典型应用。
C:外观模式封装了单向交互,而中介者模式封装了多向交互。
65.个人计算机由主板、CPU、内存、显卡、声卡、网卡和硬盘等配件组装而成,各个配件的交互一般通过主板来完成,针对上述场景,哪个设计模式最为合适:中介者。
66.小明正在设计一个通用数据处理软件,需要支持多个系统之间的数据传递与交换。该软件要求能够屏蔽各系统之间的直接数据交互,使其耦合松散,并且可以独立改变系统之间的交互过程。针对上述需求,采用哪个模式最为合适:中介者模式。
67.很多游戏软件中都提供了“储存/载入进度”的功能,支持玩家在中断游戏后仍然能够重新载入被储存的进度继续游戏。针对上述场景,哪个设计模式最为合适:备忘录。
68.下列关于状态模式和策略模式的描述中不准确的是:使用状态模式时,客户端需要知道环境类的状态是如何切换的。
69.要创建一个触发链,A对象行为将影响B对象,B对象行为将影响C对象……,可以使用:观察者模式。
70.MVC架构在实现上结合了多种设计模式,其中最典型的模式应用是:中介者和观察者。
71.兄弟俩要到操场上玩,临走时,跟妈妈说:“我俩玩去了,饭好了,招呼我们”。这段话所描述的场景最适合下列能哪种模式的应用场景:观察者模式。
72.小明正在设计一个报价管理模块,要求对普通客户或新客户报全价,对老客户报价统一折扣5%,对大客户报价统一折扣10%。针对上述需求,采用哪个设计模式最为合适:策略模式。
73.三国演义中刘备去东吴招亲,赵云得授3个锦囊妙计,分别是找乔国老帮忙、求吴国太放行及孙夫人断后,以助刘备顺利回归。针对上述场景,采用哪个设计模式最为合适:策略模式。
74.下列选项中不属于对象模式的是:模板方法模式。
属于的是:
A:建造者模式。
B:代理模式。
C:迭代器模式。
简答题&程序设计题
1.小王正在编写一个简单的计算器程序,要求输入两个整数和运算符号(加、减、乘、除),输出计算结果。小王用面向过程方法编写了下面的代码。请采用面向对象方法通过恰当的设计模式对小王的代码进行重构。请写出你所选择的设计模式,画出类图,并给出核心代码。
int main() {
int numa,numb; char oper; double result;
cin>>numa>>numb; cin>>oper;
switch(oper) {
case '+': result=numa+numb; break;
case '-': result=numa-numb; break;
case '*': result=numa*numb; break;
case '/': result=numa/(double)numb; break;
}
cout<<result<<endl;
return 0;
}
设计模式:策略模式。
类图:
+-------------------+
| IOperation |
+-------------------+
| +calculate(a, b) |
+-------------------+
^
|
+-------+--------+
| | |
+-----+ +-----+ +-----+
| Add | | Sub | | Mul |
+-----+ +-----+ +-----+
| | |
+-----+ +-----+ +-----+
| Div | | ... | | ... |
+-----+ +-----+ +-----+
|
+------------------------+
| Calculator |
+------------------------+
| -operation: IOperation |
| +setOperation(op) |
| +execute(a,b) |
+------------------------+
代码:
#include <iostream>
using namespace std;
// 运算策略接口
class IOperation {
public:
virtual double calculate(int a, int b) = 0; // 计算方法
virtual ~IOperation() = default;
};
// 具体运算策略:加法
class AddOperation : public IOperation {
public:
double calculate(int a, int b) override {
return a + b;
}
};
// 具体运算策略:减法
class SubOperation : public IOperation {
public:
double calculate(int a, int b) override {
return a - b;
}
};
// 具体运算策略:乘法
class MulOperation : public IOperation {
public:
double calculate(int a, int b) override {
return a * b;
}
};
// 具体运算策略:除法
class DivOperation : public IOperation {
public:
double calculate(int a, int b) override {
if (b == 0) {
throw runtime_error("Division by zero!");
}
return static_cast<double>(a) / b;
}
};
// 上下文类:计算器
class Calculator {
private:
IOperation* operation; // 当前运算策略
public:
void setOperation(IOperation* op) {
operation = op;
}
double execute(int a, int b) {
return operation->calculate(a, b);
}
};
int main() {
int numa, numb;
char oper;
double result;
// 输入
cin >> numa >> numb;
cin >> oper;
// 创建计算器
Calculator calc;
// 根据运算符选择运算策略
switch (oper) {
case '+': calc.setOperation(new AddOperation()); break;
case '-': calc.setOperation(new SubOperation()); break;
case '*': calc.setOperation(new MulOperation()); break;
case '/': calc.setOperation(new DivOperation()); break;
default:
cerr << "Invalid operator!" << endl;
return -1;
}
// 执行计算并输出结果
try {
result = calc.execute(numa, numb);
cout << result << endl;
} catch (const runtime_error& e) {
cerr << e.what() << endl;
}
return 0;
}
2.请为一校服制造厂编写一个校服生产子系统。该工厂可为多家学校生产校服,包括秋季校服和夏季校服。一套秋季校服含一件长袖上衣和一条秋季长裤,一套夏季校服含一件短袖衬衣、一件短袖T恤、一条夏季长裤和一条短裤。不同学校校服款式不同。请设计一个子系统为三所学校(一中、二中、三中)分别生产秋季校服和夏季校服(均码)。例如,当用户输入“一中+夏季”时,系统就会生产出一套一中夏季校服;当用户输入“一中+秋季”时,系统生产出一套一中秋季校服。请写出你所选择的设计模式,画出类图,并给出核心代码。
设计模式:抽象工厂模式。
类图:
+-----------------------+
| IUniformFactory | <--- 抽象工厂
+-----------------------+
| +createTop(): ITop |
| +createPants(): IPants|
+-----------------------+
^
|
+-------------------------+ +------------------------+
| School1UniformFactory | | School2UniformFactory |
+-------------------------+ +------------------------+
| +createTop() | | +createTop() |
| +createPants() | | +createPants() |
+-------------------------+ +------------------------+
| |
+----------+------------+ +--------+--------------+
| SummerTop | | SummerTop |
+-----------------------+ +-----------------------+
| WinterTop | | WinterTop |
+-----------------------+ +-----------------------+
|
+-----------------------+
| SummerPants |
+-----------------------+
| WinterPants |
+-----------------------+
代码:
#include <iostream>
#include <memory>
using namespace std;
// 抽象产品类
class ITop {
public:
virtual void display() = 0;
virtual ~ITop() = default;
};
class IPants {
public:
virtual void display() = 0;
virtual ~IPants() = default;
};
// 具体产品类:夏季校服上衣、秋季校服上衣
class SummerTop : public ITop {
public:
void display() override {
cout << "Summer Top: Short Sleeve Shirt" << endl;
}
};
class WinterTop : public ITop {
public:
void display() override {
cout << "Winter Top: Long Sleeve Shirt" << endl;
}
};
// 具体产品类:夏季裤子、秋季裤子
class SummerPants : public IPants {
public:
void display() override {
cout << "Summer Pants: Summer Long Pants and Shorts" << endl;
}
};
class WinterPants : public IPants {
public:
void display() override {
cout << "Winter Pants: Fall Long Pants" << endl;
}
};
// 抽象工厂类:校服工厂
class IUniformFactory {
public:
virtual unique_ptr<ITop> createTop() = 0;
virtual unique_ptr<IPants> createPants() = 0;
virtual ~IUniformFactory() = default;
};
// 具体工厂类:为一中生产校服
class School1UniformFactory : public IUniformFactory {
public:
unique_ptr<ITop> createTop() override {
return make_unique<WinterTop>(); // 一中秋季校服
}
unique_ptr<IPants> createPants() override {
return make_unique<WinterPants>(); // 一中秋季裤子
}
};
class School2UniformFactory : public IUniformFactory {
public:
unique_ptr<ITop> createTop() override {
return make_unique<SummerTop>(); // 二中夏季校服
}
unique_ptr<IPants> createPants() override {
return make_unique<SummerPants>(); // 二中夏季裤子
}
};
class School3UniformFactory : public IUniformFactory {
public:
unique_ptr<ITop> createTop() override {
return make_unique<SummerTop>(); // 三中夏季校服
}
unique_ptr<IPants> createPants() override {
return make_unique<SummerPants>(); // 三中夏季裤子
}
};
// 客户端:根据输入选择校服生产
void produceUniform(IUniformFactory& factory) {
auto top = factory.createTop();
auto pants = factory.createPants();
top->display();
pants->display();
}
int main() {
string school, season;
cout << "Enter school and season (e.g., 'School1 Summer'): ";
cin >> school >> season;
if (school == "School1" && season == "Summer") {
School1UniformFactory factory;
produceUniform(factory);
} else if (school == "School2" && season == "Summer") {
School2UniformFactory factory;
produceUniform(factory);
} else if (school == "School3" && season == "Summer") {
School3UniformFactory factory;
produceUniform(factory);
} else if (school == "School1" && season == "Winter") {
School1UniformFactory factory;
produceUniform(factory);
} else {
cout << "Invalid input!" << endl;
}
return 0;
}
3.小王正在设计一个导出数据的应用框架。客户要求:导出数据可能存储成不同的文件格式,例如:文本格式、数据库备份形式、Excel格式、Xml格式等等,并且,不管什么格式,导出数据文件都分成三个部分,分别是文件头、文件体和文件尾,在文件头部分,需要描述如下信息:分公司或门市点编号、导出数据的日期,对于文本格式,中间用逗号分隔,在文件体部分,需要描述如下信息:表名称、然后分条描述数据,对于文本格式,表名称单独占一行,数据描述一行算一条数据,字段间用逗号分隔,在文件尾部分,需要描述如下信息:输出人。请写出你所选择的设计模式,画出类图,并给出核心代码。
设计模式:模板方法模式。
类图:
+---------------------+
| DataExporter | <--- 抽象类(模板方法模式)
+---------------------+
| +exportData() |
| +writeHeader() |
| +writeBody() |
| +writeFooter() |
+---------------------+
^
|
+--------------------------+ +------------------------+ +--------------------+
| TextDataExporter | | ExcelDataExporter | | XmlDataExporter |
+--------------------------+ +------------------------+ +--------------------+
| +writeHeader() | | +writeHeader() | | +writeHeader() |
| +writeBody() | | +writeBody() | | +writeBody() |
| +writeFooter() | | +writeFooter() | | +writeFooter() |
+--------------------------+ +------------------------+ +--------------------+
^
|
+------------------+
| ExportFactory |
+------------------+
| +createExporter()|
+------------------+
代码:
#include <iostream>
#include <fstream>
#include <memory>
using namespace std;
// 抽象类:导出数据的模板
class DataExporter {
public:
virtual void exportData() {
writeHeader();
writeBody();
writeFooter();
}
protected:
virtual void writeHeader() = 0;
virtual void writeBody() = 0;
virtual void writeFooter() = 0;
virtual ~DataExporter() = default;
};
// 具体导出格式类:文本格式
class TextDataExporter : public DataExporter {
protected:
void writeHeader() override {
cout << "Text File Header: Company ID, Export Date" << endl;
}
void writeBody() override {
cout << "Text File Body: Table Name, Data" << endl;
cout << "table1" << endl;
cout << "1, John, 30" << endl;
cout << "2, Jane, 28" << endl;
}
void writeFooter() override {
cout << "Text File Footer: Output by XYZ" << endl;
}
};
// 具体导出格式类:Excel格式
class ExcelDataExporter : public DataExporter {
protected:
void writeHeader() override {
cout << "Excel File Header: Company ID, Export Date" << endl;
}
void writeBody() override {
cout << "Excel File Body: Table Name, Data" << endl;
cout << "table1" << endl;
cout << "1\tJohn\t30" << endl;
cout << "2\tJane\t28" << endl;
}
void writeFooter() override {
cout << "Excel File Footer: Output by XYZ" << endl;
}
};
// 具体导出格式类:XML格式
class XmlDataExporter : public DataExporter {
protected:
void writeHeader() override {
cout << "XML File Header: <CompanyID>123</CompanyID>" << endl;
}
void writeBody() override {
cout << "<Table>" << endl;
cout << "<Name>table1</Name>" << endl;
cout << "<Row><ID>1</ID><Name>John</Name><Age>30</Age></Row>" << endl;
cout << "<Row><ID>2</ID><Name>Jane</Name><Age>28</Age></Row>" << endl;
cout << "</Table>" << endl;
}
void writeFooter() override {
cout << "<Footer>Output by XYZ</Footer>" << endl;
}
};
// 工厂类:根据用户输入返回不同格式的导出器
class ExportFactory {
public:
static unique_ptr<DataExporter> createExporter(const string& format) {
if (format == "text") {
return make_unique<TextDataExporter>();
} else if (format == "excel") {
return make_unique<ExcelDataExporter>();
} else if (format == "xml") {
return make_unique<XmlDataExporter>();
} else {
throw runtime_error("Invalid format!");
}
}
};
int main() {
string format;
cout << "Enter the export format (text, excel, xml): ";
cin >> format;
try {
auto exporter = ExportFactory::createExporter(format);
exporter->exportData();
} catch (const exception& e) {
cout << e.what() << endl;
}
return 0;
}
4.在下面的TicketMaker类(见下表)中,每次调用getNextTicketNumber方法都会返回1000,1001,1002…的数列。我们可以用它生成票的编号或是其他序列号。在现在该类的实现方式下,我们可以生成多个该类的实例。请修改代码,确保只能生成一个该类的实例。
public class TicketMaker
{
private int ticket = 1000;
public int getNextTicketNumber()
{
return ticket++;
}
}
答案:
public class TicketMaker {
private int ticket = 1000;
// 私有的静态变量,指向唯一的实例
private static TicketMaker instance = new TicketMaker();
// 私有的构造方法,防止外部创建实例
private TicketMaker() { }
// 提供公共的静态方法来获取该类的唯一实例
public static TicketMaker getInstance() {
return instance;
}
// 获取下一个票号的方法
public int getNextTicketNumber() {
return ticket++;
}
}
5.请你按照单例模式的思想,重新实现下面给出的DBConnections类,确保系统中该类的实例对象最多只能存在三个。
class DBConnections {
public:
DBConnections ( ) { ... }
~ DBConnections ( ) { ... }
void ConnectionInfo ( ) { ... }
};
#include <iostream>
#include <vector>
#include <memory>
class DBConnections {
private:
// 私有静态变量,用于存储最多3个实例
static std::vector<std::shared_ptr<DBConnections>> instances;
static int maxInstances; // 最大实例数量
static int instanceCounter; // 当前实例计数器,用于轮转分配
// 私有构造函数,防止外部直接创建实例
DBConnections() {
std::cout << "DBConnection Created\n";
}
public:
// 析构函数
~DBConnections() {
std::cout << "DBConnection Destroyed\n";
}
// 静态方法,返回最多三个实例中的一个
static std::shared_ptr<DBConnections> getInstance() {
if (instances.size() < maxInstances) {
// 如果实例数小于最大值,创建新的实例并存入vector
instances.push_back(std::shared_ptr<DBConnections>(new DBConnections()));
}
// 轮转分配现有实例
auto instance = instances[instanceCounter % maxInstances];
instanceCounter++;
return instance;
}
// 模拟连接信息的方法
void ConnectionInfo() {
std::cout << "DB Connection info: Instance address: " << this << std::endl;
}
};
// 静态成员初始化
std::vector<std::shared_ptr<DBConnections>> DBConnections::instances;
int DBConnections::maxInstances = 3;
int DBConnections::instanceCounter = 0;
// 测试代码
int main() {
auto conn1 = DBConnections::getInstance();
conn1->ConnectionInfo();
auto conn2 = DBConnections::getInstance();
conn2->ConnectionInfo();
auto conn3 = DBConnections::getInstance();
conn3->ConnectionInfo();
auto conn4 = DBConnections::getInstance(); // 将返回第一个实例
conn4->ConnectionInfo();
return 0;
}
6.小王正在开发一套视频监控系统,考虑到Windows Media Player和Real Player是两种常用的媒体播放器,尽管它们的API结构和调用方法存在区别,但这套应用程序必须支持这两种播放器API,而且在将来可能还需要支持新的媒体播放器。请你针对上面的描述,帮助小王进行设计,给出设计思路及所采用的设计模式,画出类图,并写出关键代码。
设计模式:桥接模式。
类图:
+-------------------+
| MediaPlayer | <-- 抽象类(桥接模式)
+-------------------+
| +play() |
| +pause() |
| +stop() |
+-------------------+
^
|
+------------------------+ +-----------------------+
| WindowsMediaPlayer | | RealPlayer |
+------------------------+ +-----------------------+
| +play() | | +play() |
| +pause() | | +pause() |
| +stop() | | +stop() |
+------------------------+ +-----------------------+
^
|
+-----------------+
| PlayerControl | <-- 策略模式
+-----------------+
| +control(player)|
+-----------------+
^
|
+-----------------------+
| ConcretePlayerControl |
+-----------------------+
| +control(player) |
+-----------------------+
代码:
#include <iostream>
#include <memory>
// 抽象类:媒体播放器(桥接模式)
class MediaPlayer {
public:
virtual void play() = 0;
virtual void pause() = 0;
virtual void stop() = 0;
virtual ~MediaPlayer() = default;
};
// 具体实现类:Windows Media Player
class WindowsMediaPlayer : public MediaPlayer {
public:
void play() override {
std::cout << "Windows Media Player: Playing video." << std::endl;
}
void pause() override {
std::cout << "Windows Media Player: Paused video." << std::endl;
}
void stop() override {
std::cout << "Windows Media Player: Stopped video." << std::endl;
}
};
// 具体实现类:Real Player
class RealPlayer : public MediaPlayer {
public:
void play() override {
std::cout << "Real Player: Playing video." << std::endl;
}
void pause() override {
std::cout << "Real Player: Paused video." << std::endl;
}
void stop() override {
std::cout << "Real Player: Stopped video." << std::endl;
}
};
// 控制播放器的策略(策略模式)
class PlayerControl {
public:
virtual void control(std::shared_ptr<MediaPlayer> player) = 0;
virtual ~PlayerControl() = default;
};
// 具体控制策略:控制播放
class ConcretePlayerControl : public PlayerControl {
public:
void control(std::shared_ptr<MediaPlayer> player) override {
player->play(); // 控制播放器播放
}
};
// 客户端代码
int main() {
// 创建不同的播放器实例
std::shared_ptr<MediaPlayer> windowsPlayer = std::make_shared<WindowsMediaPlayer>();
std::shared_ptr<MediaPlayer> realPlayer = std::make_shared<RealPlayer>();
// 创建控制策略
ConcretePlayerControl controlStrategy;
// 使用控制策略控制不同的播放器
std::cout << "Using Windows Media Player:" << std::endl;
controlStrategy.control(windowsPlayer); // 使用Windows播放器
std::cout << "\nUsing Real Player:" << std::endl;
controlStrategy.control(realPlayer); // 使用Real播放器
return 0;
}
7.开发一个计算机操作系统的线程调度程序,要求实现时间片调度和抢占调度这2种调度算法,支持Windows、Unix和Linux这3个操作系统,并且将来有可能会增加新的调度算法和支持新的操作系统,请选择恰当的设计模式解决该问题,画出类图,写出关键代码。(不考虑线程调度算法的具体代码实现)。
设计模式:策略模式,工厂方法模式。
类图:
+------------------------+
| Scheduler | <---- 抽象调度器(策略模式)
+------------------------+
| +schedule() |
+------------------------+
^
|
+----------------+--------------------+
| |
+--------------------+ +--------------------+
| RoundRobinScheduler| | PreemptiveScheduler|
+--------------------+ +--------------------+
| +schedule() | | +schedule() |
+--------------------+ +--------------------+
+------------------------+
| OSchedulerFactory | <---- 抽象工厂(工厂方法模式)
+------------------------+
| +createScheduler() |
+------------------------+
^
|
+------------------------+ +------------------------+ +------------------------+
| WindowsSchedulerFactory| | UnixSchedulerFactory | | LinuxSchedulerFactory |
+------------------------+ +------------------------+ +------------------------+
| +createScheduler() | | +createScheduler() | | +createScheduler() |
+------------------------+ +------------------------+ +------------------------+
代码:
#include <iostream>
#include <memory>
// 策略模式:调度算法接口
class Scheduler {
public:
virtual void schedule() = 0; // 调度算法
virtual ~Scheduler() = default;
};
// 具体策略:时间片调度(轮转调度)
class RoundRobinScheduler : public Scheduler {
public:
void schedule() override {
std::cout << "Scheduling using Round Robin Algorithm." << std::endl;
}
};
// 具体策略:抢占式调度
class PreemptiveScheduler : public Scheduler {
public:
void schedule() override {
std::cout << "Scheduling using Preemptive Scheduling Algorithm." << std::endl;
}
};
// 工厂方法模式:调度器工厂接口
class OSchedulerFactory {
public:
virtual std::shared_ptr<Scheduler> createScheduler() = 0; // 创建调度器
virtual ~OSchedulerFactory() = default;
};
// 具体工厂:Windows调度器工厂
class WindowsSchedulerFactory : public OSchedulerFactory {
public:
std::shared_ptr<Scheduler> createScheduler() override {
// 这里可以根据需要选择不同的调度算法
return std::make_shared<RoundRobinScheduler>(); // 假设Windows使用时间片轮转调度
}
};
// 具体工厂:Unix调度器工厂
class UnixSchedulerFactory : public OSchedulerFactory {
public:
std::shared_ptr<Scheduler> createScheduler() override {
return std::make_shared<PreemptiveScheduler>(); // 假设Unix使用抢占式调度
}
};
// 具体工厂:Linux调度器工厂
class LinuxSchedulerFactory : public OSchedulerFactory {
public:
std::shared_ptr<Scheduler> createScheduler() override {
return std::make_shared<RoundRobinScheduler>(); // 假设Linux使用时间片轮转调度
}
};
// 客户端代码
int main() {
// 根据操作系统选择不同的调度器工厂
std::shared_ptr<OSchedulerFactory> factory;
// 假设当前操作系统为Windows
factory = std::make_shared<WindowsSchedulerFactory>();
// 创建调度器并执行调度
std::shared_ptr<Scheduler> scheduler = factory->createScheduler();
scheduler->schedule(); // 调用具体的调度算法
// 假设切换到Unix
factory = std::make_shared<UnixSchedulerFactory>();
scheduler = factory->createScheduler();
scheduler->schedule(); // 调用具体的调度算法
return 0;
}
8.某饮料店卖饮料时,可以根据顾客的要求在饮料中加入各种配料,饮料店会根据顾客所选的饮料种类和所加入的配料来计算价格。饮料店所供应的部分饮料及配料的种类和价格如下表所示。请你选择恰当的设计模式,为该饮料店开发一个计算饮料价格的程序,要求给出设计思路,画出类图,并写出关键代码。
饮料(Beverage) 价格/杯(¥) 配料(Condiment) 价格/份(¥)
奶茶(MilkTea) 8 草莓(Strawberry) 2
奶昔(MilkShake) 9 布丁(Pudding) 3
咖啡(Coffee) 10 芝士雪酪(Cheese) 4
设计模式:装饰者模式。
类图:
+-----------------------+
| Beverage | <--- 抽象饮料类
+-----------------------+
| +getDescription() |
| +cost() |
+-----------------------+
^
|
+------------------------------------------+
| |
+------------------+ +------------------+
| MilkTea | | MilkShake |
+------------------+ +------------------+
| +getDescription()| | +getDescription()|
| +cost() | | +cost() |
+------------------+ +------------------+
^ ^
| |
+-------------------+ +----------------------+
| Condiment | | Strawberry |
+-------------------+ +----------------------+
| +getDescription() | | +getDescription() |
| +cost() | | +cost() |
+-------------------+ +----------------------+
^ ^
| |
+---------------------+ +--------------------+
| Pudding | | Cheese |
+---------------------+ +--------------------+
| +getDescription() | | +getDescription() |
| +cost() | | +cost() |
+---------------------+ +--------------------+
代码:
#include <iostream>
#include <memory>
#include <string>
// 抽象饮料类
class Beverage {
public:
virtual ~Beverage() = default;
virtual std::string getDescription() = 0; // 获取饮料描述
virtual double cost() = 0; // 计算饮料价格
};
// 具体饮料类:奶茶
class MilkTea : public Beverage {
public:
std::string getDescription() override {
return "Milk Tea";
}
double cost() override {
return 8.0; // 奶茶的基础价格
}
};
// 具体饮料类:奶昔
class MilkShake : public Beverage {
public:
std::string getDescription() override {
return "Milk Shake";
}
double cost() override {
return 9.0; // 奶昔的基础价格
}
};
// 具体饮料类:咖啡
class Coffee : public Beverage {
public:
std::string getDescription() override {
return "Coffee";
}
double cost() override {
return 10.0; // 咖啡的基础价格
}
};
// 抽象配料类:装饰器
class Condiment : public Beverage {
protected:
std::shared_ptr<Beverage> beverage;
public:
explicit Condiment(std::shared_ptr<Beverage> beverage) : beverage(std::move(beverage)) {}
};
// 具体配料类:草莓
class Strawberry : public Condiment {
public:
explicit Strawberry(std::shared_ptr<Beverage> beverage) : Condiment(std::move(beverage)) {}
std::string getDescription() override {
return beverage->getDescription() + ", Strawberry";
}
double cost() override {
return beverage->cost() + 2.0; // 草莓的价格
}
};
// 具体配料类:布丁
class Pudding : public Condiment {
public:
explicit Pudding(std::shared_ptr<Beverage> beverage) : Condiment(std::move(beverage)) {}
std::string getDescription() override {
return beverage->getDescription() + ", Pudding";
}
double cost() override {
return beverage->cost() + 3.0; // 布丁的价格
}
};
// 具体配料类:芝士
class Cheese : public Condiment {
public:
explicit Cheese(std::shared_ptr<Beverage> beverage) : Condiment(std::move(beverage)) {}
std::string getDescription() override {
return beverage->getDescription() + ", Cheese";
}
double cost() override {
return beverage->cost() + 4.0; // 芝士的价格
}
};
// 客户端代码:根据用户选择组合饮料和配料
int main() {
std::shared_ptr<Beverage> beverage = std::make_shared<MilkTea>(); // 选择奶茶
std::cout << "Description: " << beverage->getDescription() << "\n";
std::cout << "Cost: ¥" << beverage->cost() << "\n";
// 用户选择添加草莓配料
beverage = std::make_shared<Strawberry>(beverage);
std::cout << "Description: " << beverage->getDescription() << "\n";
std::cout << "Cost: ¥" << beverage->cost() << "\n";
// 用户选择添加布丁配料
beverage = std::make_shared<Pudding>(beverage);
std::cout << "Description: " << beverage->getDescription() << "\n";
std::cout << "Cost: ¥" << beverage->cost() << "\n";
// 用户选择添加芝士配料
beverage = std::make_shared<Cheese>(beverage);
std::cout << "Description: " << beverage->getDescription() << "\n";
std::cout << "Cost: ¥" << beverage->cost() << "\n";
return 0;
}
9.小王为某五星级酒店开发点餐系统。该酒店为满足客户需要,会在不同的时段提供多种不同的餐饮,其菜单的结构图如图所示。请你采用面向对象方法通过恰当的设计模式帮助小王对上述菜单进行设计。
设计模式:组合模式。
类图:
+---------------------+
| MenuItem | <--- 抽象菜单项
+---------------------+
| +getName() |
| +getPrice() |
| +getDescription() |
| +add(MenuItem) |
+---------------------+
^
|
+--------------------------------------+
| |
+------------------+ +---------------------+
| Dish | | Menu |
+------------------+ +---------------------+
| +getName() | | +getName() |
| +getPrice() | | +getDescription() |
| +getDescription()| | +add(MenuItem) |
+------------------+ | +getItems() |
+---------------------+
代码:
#include <iostream>
#include <vector>
#include <memory>
#include <string>
// 抽象菜单项
class MenuItem {
public:
virtual ~MenuItem() = default;
virtual std::string getName() const = 0;
virtual double getPrice() const = 0;
virtual std::string getDescription() const = 0;
virtual void add(std::shared_ptr<MenuItem> item) {}
};
// 具体菜单项:菜品
class Dish : public MenuItem {
private:
std::string name;
double price;
std::string description;
public:
Dish(std::string name, double price, std::string description)
: name(std::move(name)), price(price), description(std::move(description)) {}
std::string getName() const override {
return name;
}
double getPrice() const override {
return price;
}
std::string getDescription() const override {
return description;
}
};
// 具体菜单:菜单
class Menu : public MenuItem {
private:
std::string name;
std::string description;
std::vector<std::shared_ptr<MenuItem>> items;
public:
Menu(std::string name, std::string description)
: name(std::move(name)), description(std::move(description)) {}
std::string getName() const override {
return name;
}
double getPrice() const override {
double totalPrice = 0;
for (const auto& item : items) {
totalPrice += item->getPrice();
}
return totalPrice;
}
std::string getDescription() const override {
return description;
}
void add(std::shared_ptr<MenuItem> item) override {
items.push_back(std::move(item));
}
// 获取菜单项列表
const std::vector<std::shared_ptr<MenuItem>>& getItems() const {
return items;
}
};
// 打印菜单的详细信息
void printMenu(const std::shared_ptr<MenuItem>& menuItem) {
std::cout << "Menu: " << menuItem->getName() << "\n";
std::cout << "Description: " << menuItem->getDescription() << "\n";
std::cout << "Price: ¥" << menuItem->getPrice() << "\n";
// 如果是菜单,则递归打印子菜单项
if (auto menu = std::dynamic_pointer_cast<Menu>(menuItem)) {
for (const auto& item : menu->getItems()) {
printMenu(item);
}
}
}
int main() {
// 创建菜品
auto tea = std::make_shared<Dish>("Green Tea", 5.0, "A refreshing green tea");
auto coffee = std::make_shared<Dish>("Espresso", 10.0, "Strong espresso coffee");
auto croissant = std::make_shared<Dish>("Croissant", 8.0, "Fresh buttery croissant");
// 创建菜单:早餐菜单
auto breakfastMenu = std::make_shared<Menu>("Breakfast Menu", "A selection of breakfast items");
// 将菜品添加到早餐菜单
breakfastMenu->add(tea);
breakfastMenu->add(coffee);
breakfastMenu->add(croissant);
// 创建另一个菜单:午餐菜单
auto lunchMenu = std::make_shared<Menu>("Lunch Menu", "A selection of lunch items");
// 创建菜品
auto pasta = std::make_shared<Dish>("Pasta", 15.0, "Delicious pasta with tomato sauce");
auto steak = std::make_shared<Dish>("Steak", 30.0, "Grilled steak with vegetables");
// 将菜品添加到午餐菜单
lunchMenu->add(pasta);
lunchMenu->add(steak);
// 创建酒店主菜单
auto mainMenu = std::make_shared<Menu>("Hotel Main Menu", "A collection of different meal menus");
// 将各个子菜单添加到主菜单
mainMenu->add(breakfastMenu);
mainMenu->add(lunchMenu);
// 打印主菜单
printMenu(mainMenu);
return 0;
}
10.
开发一个系统帮助业务部门实现灵活的奖金计算。对于普通员工,主要有个人当月业务奖金、个人当月回款奖金等,对于部门经理,除了有普通员工的奖金外,还有团队当月业务奖金等。目前各奖金类别的计算规则如下:
个人当月业务奖金 = 个人当月销售额 * 3%
个人当月回款奖金 = 个人当月回款额 * 0.1%
团队当月业务奖金 = 团队当月销售额 * 1%
考虑到业务部门要通过调整奖金计算方式来激励士气,系统应灵活地适应各种需求变化,例如,将来可能会增加个人业务增长奖金、团队当月回款奖金、团队业务增长奖金、团队盈利奖金等奖金类别,也可能增加新的员工岗位,或变更奖金计算规则等。请写出你所选择的设计模式,画出类图,并给出核心代码。
设计模式:策略模式。
类图:
+----------------------+
| BonusCalculator | <--- 奖金计算策略接口
+----------------------+
| +calculateBonus() |
+----------------------+
^
|
+----------------------------------------+
| |
+----------------------+ +-----------------------+
| IndividualBonus | | TeamBonus | <--- 具体奖金计算策略
+----------------------+ +-----------------------+
| +calculateBonus() | | +calculateBonus() |
+----------------------+ +-----------------------+
^ ^
| |
+------------------------+ +----------------------+
| IndividualSalesBonus | | TeamSalesBonus | <--- 具体奖金类型
+------------------------+ +----------------------+
| +calculateBonus() | | +calculateBonus() |
+------------------------+ +----------------------+
代码:
#include <iostream>
#include <string>
#include <memory>
// 奖金计算策略接口
class BonusCalculator {
public:
virtual ~BonusCalculator() = default;
virtual double calculateBonus() const = 0;
};
class IndividualBonus : public BonusCalculator {
public:
IndividualBonus(double sales, double receivables)
: salesAmount(sales), receivablesAmount(receivables) {}
double calculateBonus() const override {
double salesBonus = salesAmount * 0.03; // 个人当月业务奖金 3%
double receivablesBonus = receivablesAmount * 0.001; // 个人当月回款奖金 0.1%
return salesBonus + receivablesBonus;
}
private:
double salesAmount; // 个人当月销售额
double receivablesAmount; // 个人当月回款额
};
class TeamBonus : public BonusCalculator {
public:
TeamBonus(double teamSales)
: teamSalesAmount(teamSales) {}
double calculateBonus() const override {
return teamSalesAmount * 0.01; // 团队当月业务奖金 1%
}
private:
double teamSalesAmount; // 团队当月销售额
};
class EmployeeBonus {
public:
EmployeeBonus(std::shared_ptr<BonusCalculator> strategy)
: bonusStrategy(std::move(strategy)) {}
// 计算奖金
double getBonus() const {
return bonusStrategy->calculateBonus();
}
// 设置新的奖金计算策略(适应不同的员工类型)
void setBonusStrategy(std::shared_ptr<BonusCalculator> strategy) {
bonusStrategy = std::move(strategy);
}
private:
std::shared_ptr<BonusCalculator> bonusStrategy; // 当前奖金计算策略
};
int main() {
// 1. 创建不同的奖金计算策略
auto individualBonus = std::make_shared<IndividualBonus>(50000, 30000); // 个人当月销售额 5万,回款额 3万
auto teamBonus = std::make_shared<TeamBonus>(200000); // 团队当月销售额 20万
// 2. 创建员工奖金上下文,选择个人奖金计算策略
EmployeeBonus employee(individualBonus);
// 计算普通员工奖金
std::cout << "Individual Bonus: ¥" << employee.getBonus() << std::endl;
// 3. 修改为团队奖金计算策略
employee.setBonusStrategy(teamBonus);
// 计算团队奖金
std::cout << "Team Bonus: ¥" << employee.getBonus() << std::endl;
return 0;
}
11.请设计一个电子相册自动生成程序,要求该程序能够将一组图片自动生成到一个以树形结构保存的电子相册中,相册的目录采用树形结构,一级目录为年,二级目录为月,三级目录为日。每张照片可以添加音效和花边等特效。请写出你所选择的设计模式,画出类图,并给出核心代码。
设计模式:组合模式,装饰者模式。
类图:
+------------------------+
| AlbumComponent | <--- 抽象基类
+------------------------+
| +getName() |
| +display() |
+------------------------+
^
|
+---------------------+------------------------+
| |
+----------------+ +----------------+ +------------------+
| Year | | Month | | Day |
+----------------+ +----------------+ +------------------+
| +add(component)| | +add(component)| | +add(component) |
| +display() | | +display() | | +display() |
+----------------+ +----------------+ +------------------+
|
+----------------+----------------+
| |
+---------------+ +--------------------+
| Photo | | PhotoEffect |
+---------------+ +--------------------+
| +getName() | | +getDescription() |
| +display() | | +display() |
+---------------+ +--------------------+
^
|
+-----------------------------+------------------+
| |
+-------------------+ +------------------+
| SoundEffect | | BorderEffect |
+-------------------+ +------------------+
| +getDescription() | | +getDescription()|
| +display() | | +display() |
+-------------------+ +------------------+
代码:
#include <iostream>
#include <vector>
#include <memory>
#include <string>
// 抽象组件:目录节点
class AlbumComponent {
public:
virtual ~AlbumComponent() = default;
virtual std::string getName() const = 0;
virtual void display(int depth = 0) const = 0;
// 默认实现,无子类覆盖时抛异常
virtual void add(std::shared_ptr<AlbumComponent> component) {
throw std::runtime_error("Cannot add to this component.");
}
};
// 具体实现:年目录
class Year : public AlbumComponent {
private:
std::string name;
std::vector<std::shared_ptr<AlbumComponent>> children;
public:
explicit Year(const std::string& name) : name(name) {}
std::string getName() const override {
return name;
}
void add(std::shared_ptr<AlbumComponent> component) override {
children.push_back(component);
}
void display(int depth = 0) const override {
std::cout << std::string(depth * 2, ' ') << "Year: " << name << "\n";
for (const auto& child : children) {
child->display(depth + 1);
}
}
};
// 具体实现:月目录
class Month : public AlbumComponent {
private:
std::string name;
std::vector<std::shared_ptr<AlbumComponent>> children;
public:
explicit Month(const std::string& name) : name(name) {}
std::string getName() const override {
return name;
}
void add(std::shared_ptr<AlbumComponent> component) override {
children.push_back(component);
}
void display(int depth = 0) const override {
std::cout << std::string(depth * 2, ' ') << "Month: " << name << "\n";
for (const auto& child : children) {
child->display(depth + 1);
}
}
};
// 具体实现:日目录
class Day : public AlbumComponent {
private:
std::string name;
std::vector<std::shared_ptr<AlbumComponent>> children;
public:
explicit Day(const std::string& name) : name(name) {}
std::string getName() const override {
return name;
}
void add(std::shared_ptr<AlbumComponent> component) override {
children.push_back(component);
}
void display(int depth = 0) const override {
std::cout << std::string(depth * 2, ' ') << "Day: " << name << "\n";
for (const auto& child : children) {
child->display(depth + 1);
}
}
};
// 具体实现:照片
class Photo : public AlbumComponent {
private:
std::string name;
public:
explicit Photo(const std::string& name) : name(name) {}
std::string getName() const override {
return name;
}
void display(int depth = 0) const override {
std::cout << std::string(depth * 2, ' ') << "Photo: " << name << "\n";
}
};
// 装饰者基类
class PhotoEffect : public AlbumComponent {
protected:
std::shared_ptr<AlbumComponent> photo;
public:
explicit PhotoEffect(std::shared_ptr<AlbumComponent> photo) : photo(std::move(photo)) {}
void display(int depth = 0) const override {
photo->display(depth);
}
};
// 具体装饰:音效
class SoundEffect : public PhotoEffect {
public:
explicit SoundEffect(std::shared_ptr<AlbumComponent> photo) : PhotoEffect(std::move(photo)) {}
void display(int depth = 0) const override {
photo->display(depth);
std::cout << std::string(depth * 2, ' ') << " - Added Sound Effect\n";
}
};
// 具体装饰:花边
class BorderEffect : public PhotoEffect {
public:
explicit BorderEffect(std::shared_ptr<AlbumComponent> photo) : PhotoEffect(std::move(photo)) {}
void display(int depth = 0) const override {
photo->display(depth);
std::cout << std::string(depth * 2, ' ') << " - Added Border Effect\n";
}
};
int main() {
// 创建电子相册目录结构
auto year2024 = std::make_shared<Year>("2024");
auto january = std::make_shared<Month>("January");
auto day1 = std::make_shared<Day>("1st");
// 添加照片
auto photo1 = std::make_shared<Photo>("New Year Celebration");
auto photo2 = std::make_shared<Photo>("Family Dinner");
// 为照片添加特效
auto decoratedPhoto1 = std::make_shared<SoundEffect>(
std::make_shared<BorderEffect>(photo1)); // 添加音效和花边
auto decoratedPhoto2 = std::make_shared<BorderEffect>(photo2); // 仅添加花边
// 组织目录
day1->add(decoratedPhoto1);
day1->add(decoratedPhoto2);
january->add(day1);
year2024->add(january);
// 显示电子相册
year2024->display();
return 0;
}
12.某学校的差旅费报销制度规定,要根据不同的报销金额,由不同的领导审批,1万元以下科长审批,1万元至5万元之间处长审批,5万元至10万元之间副校长审批,10万元以上校长审批。最常用的编程思想是采用条件语句进行判断,但是随着差旅费报销制度的逐渐完善,可能需要判断的条件会越来越多,可能处理的逻辑也更加复杂,代码将变得难以维护。请选择恰当的设计模式解决该问题,画出类图,写出关键代码。
设计模式:责任链模式。
类图:
+-----------------------+
| Approver | <--- 抽象处理者
+-----------------------+
| +setNext(Approver) |
| +approveRequest(req) |
+-----------------------+
^
|
+-----------------+-------------------+
| |
+-------------------+ +---------------------+
| DepartmentHead | | Director |
+-------------------+ +---------------------+
| +approveRequest() | | +approveRequest() |
+-------------------+ +---------------------+
^ ^
| |
+-------------------+ +---------------------+
| VicePrincipal | | Principal |
+-------------------+ +---------------------+
| +approveRequest() | | +approveRequest() |
+-------------------+ +---------------------+
代码:
#include <iostream>
#include <memory>
#include <string>
// 抽象处理者类
class Approver {
protected:
std::shared_ptr<Approver> nextApprover; // 下一个处理者
public:
virtual ~Approver() = default;
// 设置下一个处理者
void setNext(std::shared_ptr<Approver> next) {
nextApprover = next;
}
// 处理请求
virtual void approveRequest(double amount) = 0;
};
// 具体处理者:科长
class DepartmentHead : public Approver {
public:
void approveRequest(double amount) override {
if (amount < 10000) {
std::cout << "Department Head approved the request of ¥" << amount << "\n";
} else if (nextApprover) {
nextApprover->approveRequest(amount);
} else {
std::cout << "No approver available for this amount.\n";
}
}
};
// 具体处理者:处长
class Director : public Approver {
public:
void approveRequest(double amount) override {
if (amount >= 10000 && amount <= 50000) {
std::cout << "Director approved the request of ¥" << amount << "\n";
} else if (nextApprover) {
nextApprover->approveRequest(amount);
} else {
std::cout << "No approver available for this amount.\n";
}
}
};
// 具体处理者:副校长
class VicePrincipal : public Approver {
public:
void approveRequest(double amount) override {
if (amount > 50000 && amount <= 100000) {
std::cout << "Vice Principal approved the request of ¥" << amount << "\n";
} else if (nextApprover) {
nextApprover->approveRequest(amount);
} else {
std::cout << "No approver available for this amount.\n";
}
}
};
// 具体处理者:校长
class Principal : public Approver {
public:
void approveRequest(double amount) override {
if (amount > 100000) {
std::cout << "Principal approved the request of ¥" << amount << "\n";
} else if (nextApprover) {
nextApprover->approveRequest(amount);
} else {
std::cout << "No approver available for this amount.\n";
}
}
};
int main() {
// 创建具体处理者
auto departmentHead = std::make_shared<DepartmentHead>();
auto director = std::make_shared<Director>();
auto vicePrincipal = std::make_shared<VicePrincipal>();
auto principal = std::make_shared<Principal>();
// 设置责任链
departmentHead->setNext(director);
director->setNext(vicePrincipal);
vicePrincipal->setNext(principal);
// 模拟处理请求
std::cout << "Requesting ¥8000:\n";
departmentHead->approveRequest(8000);
std::cout << "\nRequesting ¥20000:\n";
departmentHead->approveRequest(20000);
std::cout << "\nRequesting ¥75000:\n";
departmentHead->approveRequest(75000);
std::cout << "\nRequesting ¥150000:\n";
departmentHead->approveRequest(150000);
return 0;
}
13.小王准备使用面向对象的方法设计一个快餐店的简单游戏,游戏中有顾客、服务员、菜品和厨师。每个顾客都有一个服务员帮助点菜,并且可以点多个菜;每道菜都由指定厨师制作,不同的菜可能由不同的厨师制作;顾客跟服务员点完菜后,服务员通知后厨做菜。请你针对上面的描述,帮助小王选择合适的设计模式进行设计。
1)简要说明你的设计思路和选择的模式。
2)给出你设计的UML类图和实现代码。
设计模式:命令模式,工厂模式。
类图:
+-------------------+
| Command | <--- 抽象命令
+-------------------+
| +execute() |
+-------------------+
^
|
+-----------+------------+
| |
+-------------------+ +---------------------+
| DishCommand | | Factory | <--- 工厂模式
+-------------------+ +---------------------+
| -dishName | | +createDish(type) |
| -chef | +---------------------+
| +execute() |
+-------------------+
^
|
+--------------------+ +----------------+
| DishFactory | | Chef |
+--------------------+ +----------------+
| +createDish(name) | | +cookDish() |
+--------------------+ +----------------+
^
|
+-------------------+ +-------------------+
| Dish | | Waiter |
+-------------------+ +-------------------+
| -name | | +takeOrder() |
+-------------------+ | +notifyKitchen() |
+-------------------+
^
|
+--------------+
| Customer |
+--------------+
| +placeOrder()|
+--------------+
代码:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// 抽象命令类
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
};
class Chef; // 前向声明
// 具体命令类:制作菜品
class DishCommand : public Command {
private:
std::string dishName;
std::shared_ptr<Chef> chef;
public:
DishCommand(const std::string& dishName, std::shared_ptr<Chef> chef)
: dishName(dishName), chef(std::move(chef)) {}
void execute() override;
};
class Chef {
private:
std::string name;
public:
explicit Chef(std::string name) : name(std::move(name)) {}
void cookDish(const std::string& dishName) {
std::cout << name << " is cooking " << dishName << "\n";
}
};
// DishCommand execute 方法
void DishCommand::execute() {
chef->cookDish(dishName);
}
class DishFactory {
public:
static std::shared_ptr<DishCommand> createDish(const std::string& dishName, std::shared_ptr<Chef> chef) {
return std::make_shared<DishCommand>(dishName, std::move(chef));
}
};
class Waiter {
private:
std::vector<std::shared_ptr<Command>> orders;
public:
void takeOrder(std::shared_ptr<Command> order) {
orders.push_back(std::move(order));
}
void notifyKitchen() {
for (const auto& order : orders) {
order->execute();
}
orders.clear();
}
};
class Customer {
public:
void placeOrder(Waiter& waiter, const std::string& dishName, std::shared_ptr<Chef> chef) {
auto order = DishFactory::createDish(dishName, std::move(chef));
waiter.takeOrder(order);
}
};
int main() {
// 创建厨师
auto chefJohn = std::make_shared<Chef>("John");
auto chefEmily = std::make_shared<Chef>("Emily");
// 创建服务员
Waiter waiter;
// 创建顾客
Customer customer;
// 顾客下订单
customer.placeOrder(waiter, "Pasta", chefJohn);
customer.placeOrder(waiter, "Steak", chefEmily);
// 服务员通知后厨
waiter.notifyKitchen();
return 0;
}
14.小明正在开发一个病房呼叫应答仿真系统。系统中每个病房配备一个呼叫按钮和一个呼叫显示应答器,疗区大厅配备一个显示应答器和一个语音播报器。假设,按下001号病房的呼叫按钮后,那么,所有的呼叫显示应答器都会显示发出呼叫的病房号001,大厅同时语音播报该病房号001。当医护人员按下任意一处的呼叫显示应答器的应答按钮后,所有呼叫显示应答器停止显示该房间号,大厅也停止语音播报。请用恰当的设计模式实现该系统,画出类图,给出核心代码。
设计模式:观察者模式。
类图:
+--------------------+
| Subject |
+--------------------+
| +registerObserver()|
| +removeObserver() |
| +notifyObservers() |
+--------------------+
^
|
+------------------+------------------+
| |
+---------------------+ +------------------------+
| CallButton | | Observer |
+---------------------+ +------------------------+
| -observers | | +update(roomNumber) |
| +pressButton() | +------------------------+
| +pressAnswer() | ^
+---------------------+ |
|
+---------------------+ +--------------------------+
| CallDisplayUnit | | VoiceAnnouncer |
+---------------------+ +--------------------------+
| +update(roomNumber) | | +update(roomNumber) |
+---------------------+ +--------------------------+
代码:
#include <iostream>
#include <vector>
#include <memory>
#include <string>
// 抽象主体类
class Observer;
class Subject {
public:
virtual ~Subject() = default;
// 注册观察者
virtual void registerObserver(std::shared_ptr<Observer> observer) = 0;
// 移除观察者
virtual void removeObserver(std::shared_ptr<Observer> observer) = 0;
// 通知观察者
virtual void notifyObservers(const std::string& roomNumber) = 0;
};
// 抽象观察者类
class Observer {
public:
virtual ~Observer() = default;
// 更新接口
virtual void update(const std::string& roomNumber) = 0;
};
// 病房呼叫按钮
class CallButton : public Subject {
private:
std::vector<std::shared_ptr<Observer>> observers;
std::string currentRoomNumber;
public:
void registerObserver(std::shared_ptr<Observer> observer) override {
observers.push_back(observer);
}
void removeObserver(std::shared_ptr<Observer> observer) override {
observers.erase(
std::remove(observers.begin(), observers.end(), observer),
observers.end());
}
void notifyObservers(const std::string& roomNumber) override {
for (const auto& observer : observers) {
observer->update(roomNumber);
}
}
// 按下呼叫按钮
void pressButton(const std::string& roomNumber) {
currentRoomNumber = roomNumber;
std::cout << "CallButton: Room " << roomNumber << " is calling.\n";
notifyObservers(roomNumber);
}
// 按下应答按钮
void pressAnswer() {
std::cout << "CallButton: Answering call for room " << currentRoomNumber << ".\n";
notifyObservers(""); // 通知清空
}
};
// 病房显示器
class CallDisplayUnit : public Observer {
private:
std::string displayID;
public:
explicit CallDisplayUnit(std::string id) : displayID(std::move(id)) {}
void update(const std::string& roomNumber) override {
if (roomNumber.empty()) {
std::cout << "Display " << displayID << ": Call cleared.\n";
} else {
std::cout << "Display " << displayID << ": Displaying call from room " << roomNumber << ".\n";
}
}
};
// 语音播报器
class VoiceAnnouncer : public Observer {
public:
void update(const std::string& roomNumber) override {
if (roomNumber.empty()) {
std::cout << "VoiceAnnouncer: Stopping announcements.\n";
} else {
std::cout << "VoiceAnnouncer: Announcing call from room " << roomNumber << ".\n";
}
}
};
int main() {
// 创建呼叫按钮(主体)
auto callButton = std::make_shared<CallButton>();
// 创建观察者
auto display1 = std::make_shared<CallDisplayUnit>("001");
auto display2 = std::make_shared<CallDisplayUnit>("002");
auto voiceAnnouncer = std::make_shared<VoiceAnnouncer>();
// 注册观察者
callButton->registerObserver(display1);
callButton->registerObserver(display2);
callButton->registerObserver(voiceAnnouncer);
// 按下呼叫按钮
callButton->pressButton("001");
// 按下应答按钮
callButton->pressAnswer();
return 0;
}
15.小王正在为某公司设计开发一套物业租赁管理系统,该公司有多种类型的物业,如公寓、商铺等,并且在将来可能会增加新的物业类型,如别墅、车库等;公司的经纪每租出一个物业,主管就会收到相应的租赁信息。请你针对上面的描述,帮助小王选择合适的设计模式进行设计。
1)简要说明你的设计思路和选择的模式。
2)给出你设计的UML类图和实现代码。
设计模式:工厂模式,观察者模式。
类图:
+----------------------+
| Property | <--- 抽象物业类
+----------------------+
| +rent() |
| +getInfo() |
+----------------------+
^
|
+-----------------+-----------------+
| |
+---------------------+ +---------------------+
| Apartment | | Shop |
+---------------------+ +---------------------+
| +getInfo() | | +getInfo() |
+---------------------+ +---------------------+
+----------------------+
| PropertyFactory | <--- 工厂模式
+----------------------+
| +createProperty() |
+----------------------+
+----------------------+
| Observer | <--- 观察者模式
+----------------------+
| +update(info) |
+----------------------+
^
|
+----------------------+
| Supervisor |
+----------------------+
| +update(info) |
+----------------------+
+----------------------+
| Broker |
+----------------------+
| +rentProperty() |
| +registerObserver() |
| +removeObserver() |
+----------------------+
代码:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// 抽象物业类
class Property {
public:
virtual ~Property() = default;
// 租赁操作
virtual void rent() = 0;
// 获取物业信息
virtual std::string getInfo() const = 0;
};
// 公寓类
class Apartment : public Property {
public:
void rent() override {
std::cout << "Apartment rented.\n";
}
std::string getInfo() const override {
return "Property Type: Apartment";
}
};
// 商铺类
class Shop : public Property {
public:
void rent() override {
std::cout << "Shop rented.\n";
}
std::string getInfo() const override {
return "Property Type: Shop";
}
};
class PropertyFactory {
public:
// 创建物业对象
static std::shared_ptr<Property> createProperty(const std::string& type) {
if (type == "Apartment") {
return std::make_shared<Apartment>();
} else if (type == "Shop") {
return std::make_shared<Shop>();
}
throw std::invalid_argument("Unknown property type.");
}
};
// 抽象观察者
class Observer {
public:
virtual ~Observer() = default;
// 更新通知
virtual void update(const std::string& info) = 0;
};
// 具体观察者:主管
class Supervisor : public Observer {
private:
std::string name;
public:
explicit Supervisor(std::string name) : name(std::move(name)) {}
void update(const std::string& info) override {
std::cout << "Supervisor " << name << " received notification: " << info << "\n";
}
};
// 经纪类
class Broker {
private:
std::vector<std::shared_ptr<Observer>> observers;
public:
void registerObserver(std::shared_ptr<Observer> observer) {
observers.push_back(observer);
}
void removeObserver(std::shared_ptr<Observer> observer) {
observers.erase(
std::remove(observers.begin(), observers.end(), observer),
observers.end());
}
void notifyObservers(const std::string& info) {
for (const auto& observer : observers) {
observer->update(info);
}
}
void rentProperty(const std::shared_ptr<Property>& property) {
property->rent();
notifyObservers(property->getInfo());
}
};
int main() {
// 创建工厂和经纪对象
auto broker = std::make_shared<Broker>();
// 注册主管
auto supervisor1 = std::make_shared<Supervisor>("Alice");
auto supervisor2 = std::make_shared<Supervisor>("Bob");
broker->registerObserver(supervisor1);
broker->registerObserver(supervisor2);
// 创建物业
auto apartment = PropertyFactory::createProperty("Apartment");
auto shop = PropertyFactory::createProperty("Shop");
// 租赁物业
broker->rentProperty(apartment);
broker->rentProperty(shop);
return 0;
}
16.开发一个消防应急响应系统,火灾探测器(FireDetector)发现火灾异常后将自动传递信号给各种响应设备,例如警示灯(WarningLight)将闪烁(flicker())、报警器(Alarm)将发出警报(alarm())、安全逃生门(SecurityDoor)将自动开启(open())、隔离门(InsulatedDoor)将自动关闭(close())等,每一种响应设备的行为由专门的程序来控制。请写出你所选择的设计模式,画出类图,并给出核心代码。
设计模式:观察者模式。
类图:
+----------------------+
| Subject |
+----------------------+
| +registerObserver() |
| +removeObserver() |
| +notifyObservers() |
+----------------------+
^
|
+---------------+--------------+
| |
+--------------------+ +--------------------+
| FireDetector | | Observer |
+--------------------+ +--------------------+
| -observers | | +update() |
| +registerObserver()| +--------------------+
| +removeObserver() | ^
| +notifyObservers() | |
+--------------------+ +---------------------------+
| WarningLight |
+---------------------------+
| +update() |
| +flicker() |
+---------------------------+
| Alarm |
+---------------------------+
| +update() |
| +alarm() |
+---------------------------+
| SecurityDoor |
+---------------------------+
| +update() |
| +open() |
+---------------------------+
| InsulatedDoor |
+---------------------------+
| +update() |
| +close() |
+---------------------------+
代码:
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
#include <string>
// 抽象主体类
class Observer;
class Subject {
public:
virtual ~Subject() = default;
// 注册观察者
virtual void registerObserver(std::shared_ptr<Observer> observer) = 0;
// 移除观察者
virtual void removeObserver(std::shared_ptr<Observer> observer) = 0;
// 通知所有观察者
virtual void notifyObservers() = 0;
};
// 抽象观察者类
class Observer {
public:
virtual ~Observer() = default;
// 更新接口
virtual void update() = 0;
};
// 具体主体类:火灾探测器
class FireDetector : public Subject {
private:
std::vector<std::shared_ptr<Observer>> observers;
public:
void registerObserver(std::shared_ptr<Observer> observer) override {
observers.push_back(observer);
}
void removeObserver(std::shared_ptr<Observer> observer) override {
observers.erase(
std::remove(observers.begin(), observers.end(), observer),
observers.end());
}
void notifyObservers() override {
for (const auto& observer : observers) {
observer->update();
}
}
// 检测到火灾
void detectFire() {
std::cout << "FireDetector: Fire detected! Notifying all responders...\n";
notifyObservers();
}
};
// 具体观察者类:警示灯
class WarningLight : public Observer {
public:
void update() override {
flicker();
}
void flicker() {
std::cout << "WarningLight: Flashing warning light!\n";
}
};
// 具体观察者类:报警器
class Alarm : public Observer {
public:
void update() override {
alarm();
}
void alarm() {
std::cout << "Alarm: Ringing alarm!\n";
}
};
// 具体观察者类:安全逃生门
class SecurityDoor : public Observer {
public:
void update() override {
open();
}
void open() {
std::cout << "SecurityDoor: Opening security door for evacuation.\n";
}
};
// 具体观察者类:隔离门
class InsulatedDoor : public Observer {
public:
void update() override {
close();
}
void close() {
std::cout << "InsulatedDoor: Closing insulated door to contain fire.\n";
}
};
int main() {
// 创建火灾探测器(主体)
auto fireDetector = std::make_shared<FireDetector>();
// 创建响应设备(观察者)
auto warningLight = std::make_shared<WarningLight>();
auto alarm = std::make_shared<Alarm>();
auto securityDoor = std::make_shared<SecurityDoor>();
auto insulatedDoor = std::make_shared<InsulatedDoor>();
// 注册观察者
fireDetector->registerObserver(warningLight);
fireDetector->registerObserver(alarm);
fireDetector->registerObserver(securityDoor);
fireDetector->registerObserver(insulatedDoor);
// 检测到火灾
fireDetector->detectFire();
return 0;
}
17.小明为某银行开发一个报警系统,该系统功能描述如下,请你帮助小明完成设计,给出设计模式的名称,画出类图,写出关键代码。
有一个金库
金库与警报中心相连
金库里有警铃和正常通话用的电话
金库里有时钟,监视着现在的时间
白天的时间范围是 9:0016:59,晚上的时间范围是 17:0023:59 和 0:00~8:59
金库只能在白天使用
白天使用金库的话,会在警报中心留下记录
晚上使用金库的话,会向警报中心发送紧急通知
任何时候都可以使用警铃
使用警铃的话,会向警报中心发送紧急事态通知
任何时候都可以使用电话(但晚上只有留言电话)
白天使用电话的话,会呼叫警报中心
晚上使用电话,会呼叫警报中心的留言电话
设计模式:状态模式。
类图:
+---------------------+
| Context | <--- 上下文类
+---------------------+
| -currentState |
| +setTime(hour) |
| +changeState(state) |
| +callPhone() |
| +useVault() |
| +pressBell() |
+---------------------+
^
|
+-----------------+--------------------+
| |
+--------------------+ +--------------------+
| DayState | | NightState |
+--------------------+ +--------------------+
| +callPhone() | | +callPhone() |
| +useVault() | | +useVault() |
| +pressBell() | | +pressBell() |
+--------------------+ +--------------------+
+---------------------+
| AlarmCenter | <--- 警报中心
+---------------------+
| +log(message) |
| +emergency(message) |
+---------------------+
代码:
#include <iostream>
#include <string>
#include <memory>
// 上下文类的前向声明
class Context;
// 抽象状态类
class State {
public:
virtual ~State() = default;
virtual void useVault(Context& context) = 0;
virtual void callPhone(Context& context) = 0;
virtual void pressBell(Context& context) = 0;
};
class AlarmCenter {
public:
static void log(const std::string& message) {
std::cout << "AlarmCenter Log: " << message << "\n";
}
static void emergency(const std::string& message) {
std::cout << "AlarmCenter Emergency: " << message << "\n";
}
};
#include <iostream>
// 白天状态
class DayState : public State {
public:
static std::shared_ptr<State> getInstance() {
static std::shared_ptr<State> instance = std::make_shared<DayState>();
return instance;
}
void useVault(Context& context) override {
AlarmCenter::log("Using vault during the day.");
}
void callPhone(Context& context) override {
AlarmCenter::log("Calling the Alarm Center.");
}
void pressBell(Context& context) override {
AlarmCenter::emergency("Emergency bell pressed during the day.");
}
};
// 夜晚状态
class NightState : public State {
public:
static std::shared_ptr<State> getInstance() {
static std::shared_ptr<State> instance = std::make_shared<NightState>();
return instance;
}
void useVault(Context& context) override {
AlarmCenter::emergency("Unauthorized vault access at night!");
}
void callPhone(Context& context) override {
AlarmCenter::log("Calling the Alarm Center's voicemail.");
}
void pressBell(Context& context) override {
AlarmCenter::emergency("Emergency bell pressed at night.");
}
};
class Context {
private:
std::shared_ptr<State> currentState;
public:
Context() : currentState(DayState::getInstance()) {}
void setTime(int hour) {
if (hour >= 9 && hour < 17) {
changeState(DayState::getInstance());
} else {
changeState(NightState::getInstance());
}
}
void changeState(std::shared_ptr<State> state) {
currentState = state;
std::cout << "Context: State changed to "
<< (currentState == DayState::getInstance() ? "DayState" : "NightState") << ".\n";
}
void useVault() {
currentState->useVault(*this);
}
void callPhone() {
currentState->callPhone(*this);
}
void pressBell() {
currentState->pressBell(*this);
}
};
int main() {
Context context;
// 设置时间为白天
std::cout << "Setting time to 10:00 (Day).\n";
context.setTime(10);
context.useVault();
context.callPhone();
context.pressBell();
// 设置时间为晚上
std::cout << "\nSetting time to 20:00 (Night).\n";
context.setTime(20);
context.useVault();
context.callPhone();
context.pressBell();
return 0;
}
18.小明正在开发一个温度自动调节系统,该系统能够根据用户设置的温度值自动调节温度。当系统开启时,它会读取用户设置的期望温度值T,若当前温度低于T,它将温度提升到T,若当前温度高于T,它将温度降为T。当系统关闭时,它将停止调节温度。当系统开启时,它可以接受温度设置及关闭系统的指令,当系统关闭时,它只接受开启系统的指令。请用恰当的设计模式设计该系统,画出类图,给出核心代码。
设计模式:状态模式。
类图:
+--------------------+
| Context | <--- 上下文类
+--------------------+
| -currentState |
| +setState(state) |
| +setTemperature(T) |
| +turnOn() |
| +turnOff() |
+--------------------+
^
|
+---------------------+---------------------+
| |
+------------------+ +------------------+
| OnState | | OffState |
+------------------+ +------------------+
| +setTemperature()| | +setTemperature()|
| +turnOn() | | +turnOn() |
| +turnOff() | | +turnOff() |
+------------------+ +------------------+
代码:
#include <iostream>
#include <memory>
class Context; // 前向声明
// 抽象状态类
class State {
public:
virtual ~State() = default;
virtual void setTemperature(Context& context, int temperature) = 0;
virtual void turnOn(Context& context) = 0;
virtual void turnOff(Context& context) = 0;
};
class Context {
private:
std::shared_ptr<State> currentState;
int currentTemperature;
public:
Context() : currentTemperature(25) {} // 默认温度为 25℃
void setState(std::shared_ptr<State> state) {
currentState = state;
}
void setTemperature(int temperature) {
currentState->setTemperature(*this, temperature);
}
void turnOn() {
currentState->turnOn(*this);
}
void turnOff() {
currentState->turnOff(*this);
}
void adjustTemperature(int targetTemperature) {
if (currentTemperature < targetTemperature) {
std::cout << "Heating up to " << targetTemperature << "℃...\n";
currentTemperature = targetTemperature;
} else if (currentTemperature > targetTemperature) {
std::cout << "Cooling down to " << targetTemperature << "℃...\n";
currentTemperature = targetTemperature;
} else {
std::cout << "Temperature is already at " << targetTemperature << "℃.\n";
}
}
int getCurrentTemperature() const {
return currentTemperature;
}
};
// 开启状态
class OnState : public State {
public:
static std::shared_ptr<State> getInstance() {
static std::shared_ptr<State> instance = std::make_shared<OnState>();
return instance;
}
void setTemperature(Context& context, int temperature) override {
std::cout << "OnState: Adjusting temperature to " << temperature << "℃.\n";
context.adjustTemperature(temperature);
}
void turnOn(Context& context) override {
std::cout << "OnState: System is already ON.\n";
}
void turnOff(Context& context) override {
std::cout << "OnState: Turning off the system.\n";
context.setState(OffState::getInstance());
}
};
// 关闭状态
class OffState : public State {
public:
static std::shared_ptr<State> getInstance() {
static std::shared_ptr<State> instance = std::make_shared<OffState>();
return instance;
}
void setTemperature(Context& context, int temperature) override {
std::cout << "OffState: Cannot set temperature while system is OFF.\n";
}
void turnOn(Context& context) override {
std::cout << "OffState: Turning on the system.\n";
context.setState(OnState::getInstance());
}
void turnOff(Context& context) override {
std::cout << "OffState: System is already OFF.\n";
}
};
int main() {
Context system;
// 初始状态为关闭
system.setState(OffState::getInstance());
// 尝试设置温度(失败)
system.setTemperature(22);
// 打开系统
system.turnOn();
// 设置温度
system.setTemperature(22);
// 再次设置相同温度
system.setTemperature(22);
// 关闭系统
system.turnOff();
// 再次尝试设置温度(失败)
system.setTemperature(20);
return 0;
}
19.小王正在开发一套电影院售票系统,在该系统中需要为不同类型的用户提供不同的电影票打折方式,具体打折方案如下:(1) 学生凭学生证可享受票价7折优惠;(2) 年龄在10周岁及以下的儿童可享受每张票减免15元的优惠(原始票价需大于等于30元);(3) 影院会员卡用户除享受票价半价优惠外还可进行积分,积分累计到一定额度可换取电影院赠送的奖品。该系统在将来可能还要根据需要引入新的打折方式。请你针对上面的描述,帮助小王进行设计,给出设计思路及所采用的设计模式,画出类图,并写出关键代码。
设计模式:策略模式。
类图:
+------------------------+
| DiscountStrategy | <--- 抽象策略类
+------------------------+
| +calculate(price) |
+------------------------+
^
|
+--------------------------+-----------------------------+
| | |
+--------------------+ +------------------------+ +----------------------+
| StudentDiscount | | ChildDiscount | | MemberDiscount |
+--------------------+ +------------------------+ +----------------------+
| +calculate(price) | | +calculate(price) | | +calculate(price) |
+--------------------+ +------------------------+ | +addPoints(points) |
+----------------------+
+------------------------+
| Ticket | <--- 上下文类
+------------------------+
| -price |
| -strategy |
| +setStrategy(strategy) |
| +getPrice() |
+------------------------+
代码:
#include <iostream>
#include <memory>
// 抽象策略类
class DiscountStrategy {
public:
virtual ~DiscountStrategy() = default;
// 计算折扣后的票价
virtual double calculate(double price) = 0;
};
// 学生折扣策略
class StudentDiscount : public DiscountStrategy {
public:
double calculate(double price) override {
std::cout << "Applying student discount: 7% off.\n";
return price * 0.7;
}
};
// 儿童折扣策略
class ChildDiscount : public DiscountStrategy {
public:
double calculate(double price) override {
if (price >= 30) {
std::cout << "Applying child discount: Reduce ¥15.\n";
return price - 15;
}
std::cout << "Child discount not applicable (price < ¥30).\n";
return price;
}
};
// 会员折扣策略
class MemberDiscount : public DiscountStrategy {
private:
int points = 0; // 累计积分
public:
double calculate(double price) override {
std::cout << "Applying member discount: 50% off.\n";
double discountedPrice = price * 0.5;
addPoints(static_cast<int>(discountedPrice));
return discountedPrice;
}
void addPoints(int pointsEarned) {
points += pointsEarned;
std::cout << "Points earned: " << pointsEarned << ". Total points: " << points << ".\n";
}
};
// 电影票类
class Ticket {
private:
double price; // 原始票价
std::shared_ptr<DiscountStrategy> strategy;
public:
explicit Ticket(double price) : price(price) {}
// 设置折扣策略
void setStrategy(std::shared_ptr<DiscountStrategy> strategy) {
this->strategy = std::move(strategy);
}
// 获取折扣后的票价
double getPrice() {
if (!strategy) {
std::cout << "No discount strategy set.\n";
return price;
}
return strategy->calculate(price);
}
};
int main() {
Ticket ticket(100); // 创建票价为 100 的电影票
// 学生折扣
std::cout << "\n--- Student Discount ---\n";
ticket.setStrategy(std::make_shared<StudentDiscount>());
std::cout << "Final price: ¥" << ticket.getPrice() << "\n";
// 儿童折扣
std::cout << "\n--- Child Discount ---\n";
ticket.setStrategy(std::make_shared<ChildDiscount>());
std::cout << "Final price: ¥" << ticket.getPrice() << "\n";
// 会员折扣
std::cout << "\n--- Member Discount ---\n";
auto memberDiscount = std::make_shared<MemberDiscount>();
ticket.setStrategy(memberDiscount);
std::cout << "Final price: ¥" << ticket.getPrice() << "\n";
return 0;
}
20.小明在使用策略模式进行设计时,发现策略所对应的多个算法在实现上有很多公共功能,请你给出建议帮助小明能更好地实现复用?小明再进一步设计时,又发现这些算法的实现步骤都是一样的,只是在某些局部步骤的实现上有所不同,那么请你再帮帮小明,如何能更好地实现复用?
设计模式:模板方法模式。
类图:
+--------------------------+
| AbstractStrategy | <--- 抽象基类
+--------------------------+
| +calculate(price) |
| +baseLogic() | <--- 公共功能
| +specialLogic(price) | <--- 子类实现
+--------------------------+
^
|
+----------------------+----------------------+
| |
+----------------------+ +-----------------------+
| StudentStrategy | | MemberStrategy |
+----------------------+ +-----------------------+
| +specialLogic(price) | | +specialLogic(price) |
+----------------------+ +-----------------------+
代码:
// 抽象策略类,包含模板方法
class AbstractStrategy {
public:
virtual ~AbstractStrategy() = default;
// 模板方法:定义算法结构
double calculate(double price) {
baseLogic();
return specialLogic(price);
}
protected:
// 公共功能
void baseLogic() {
std::cout << "Applying base discount logic...\n";
}
// 子类实现的具体逻辑
virtual double specialLogic(double price) = 0;
};
// 学生策略
class StudentStrategy : public AbstractStrategy {
protected:
double specialLogic(double price) override {
std::cout << "Applying student-specific discount: 70%.\n";
return price * 0.7;
}
};
// 会员策略
class MemberStrategy : public AbstractStrategy {
protected:
double specialLogic(double price) override {
std::cout << "Applying member-specific discount: 50%.\n";
return price * 0.5;
}
};
// 使用示例
int main() {
std::shared_ptr<AbstractStrategy> studentStrategy = std::make_shared<StudentStrategy>();
std::shared_ptr<AbstractStrategy> memberStrategy = std::make_shared<MemberStrategy>();
std::cout << "Student price: ¥" << studentStrategy->calculate(100) << "\n";
std::cout << "Member price: ¥" << memberStrategy->calculate(100) << "\n";
return 0;
}
算法实现步骤一致,但某些局部步骤不同,如何更好实现复用?
将算法的整体流程抽象为模板方法,并将可变步骤抽象为钩子方法或抽象方法。
钩子方法:提供默认实现,子类可以选择性覆盖。
抽象方法:子类必须实现。
class AbstractStrategy {
public:
virtual ~AbstractStrategy() = default;
// 模板方法:定义固定的算法流程
double calculate(double price) {
step1(); // 固定步骤
double result = step2(price); // 可变步骤
step3(); // 固定步骤
return result;
}
protected:
// 固定步骤 1
void step1() {
std::cout << "Step 1: Preparing discount calculation...\n";
}
// 可变步骤 2(抽象方法,子类必须实现)
virtual double step2(double price) = 0;
// 固定步骤 3
void step3() {
std::cout << "Step 3: Finalizing discount process.\n";
}
};
// 学生策略
class StudentStrategy : public AbstractStrategy {
protected:
double step2(double price) override {
std::cout << "Step 2: Applying student-specific discount: 70%.\n";
return price * 0.7;
}
};
// 会员策略
class MemberStrategy : public AbstractStrategy {
protected:
double step2(double price) override {
std::cout << "Step 2: Applying member-specific discount: 50%.\n";
return price * 0.5;
}
};
// 使用示例
int main() {
std::shared_ptr<AbstractStrategy> studentStrategy = std::make_shared<StudentStrategy>();
std::shared_ptr<AbstractStrategy> memberStrategy = std::make_shared<MemberStrategy>();
std::cout << "Student price: ¥" << studentStrategy->calculate(100) << "\n";
std::cout << "Member price: ¥" << memberStrategy->calculate(100) << "\n";
return 0;
}
21.当前开发一个新语言、新中间件或程序框架时,基于充分利用多核CPU能力等方面的考虑,多采用事件循环处理模型+回调函数的设计方式,使用该模型的示例代码和预期输出详见下表。针对该模型,请写出你所选择的设计模式,画出类图,并给出Trigger类及相关类的设计和实现,使得输出能够符合预期结果。(为简便起见,假设所有事件处理函数的原型均为void xxxx(void);)。
// 示例代码
void func01() { cout << "func01()" << endl; }
void func02() { cout << "func02()" << endl; }
void func03() { cout << "func03()" << endl; }
Trigger trigger; // 触发器
// 注册事件:
trigger.on("event01", func01);
trigger.on("event01", func02);
trigger.on("event02", func02);
trigger.on("event03", func03);
// 触发事件:
trigger.raiseEvent("event01");
trigger.raiseEvent("event02");
trigger.raiseEvent("event03");
trigger.on("event01", nullptr);
trigger.raiseEvent("event01");
trigger.raiseEvent("event02");
输出:
Process event01 start
func01()
func02()
Process event01 end
Process event02 start
func02()
Process event02 end
Process event03 start
func03()
Process event03 end
Process event02 start
func02()
Process event02 end
设计模式:观察者模式。
类图:
+-------------------+
| Trigger | <--- 事件触发器
+-------------------+
| +on(event, func) |
| +raiseEvent(event)|
+-------------------+
^
|
+----------------+----------------+
| |
+--------------------+ +--------------------+
| CallbackManager | | Callback |
+--------------------+ +--------------------+
| +addCallback() | | +execute() |
| +removeCallback() | +--------------------+
| +notifyAll() |
+--------------------+
代码:
#include <iostream>
#include <map>
#include <vector>
#include <functional>
#include <string>
class CallbackManager {
private:
std::map<std::string, std::vector<std::function<void()>>> eventCallbacks;
public:
// 注册回调
void addCallback(const std::string& event, const std::function<void()>& callback) {
if (callback) {
eventCallbacks[event].push_back(callback);
} else {
// 清空事件对应的回调
eventCallbacks[event].clear();
}
}
// 通知所有回调函数
void notifyAll(const std::string& event) {
std::cout << "Process " << event << " start\n";
if (eventCallbacks.find(event) != eventCallbacks.end()) {
for (const auto& callback : eventCallbacks[event]) {
callback();
}
}
std::cout << "Process " << event << " end\n";
}
};
class Trigger {
private:
CallbackManager callbackManager;
public:
// 注册事件
void on(const std::string& event, void (*callback)(void)) {
if (callback) {
callbackManager.addCallback(event, callback);
} else {
callbackManager.addCallback(event, nullptr);
}
}
// 触发事件
void raiseEvent(const std::string& event) {
callbackManager.notifyAll(event);
}
};#include <iostream>
using namespace std;
// 示例回调函数
void func01() { cout << "func01()" << endl; }
void func02() { cout << "func02()" << endl; }
void func03() { cout << "func03()" << endl; }
int main() {
Trigger trigger; // 触发器
// 注册事件
trigger.on("event01", func01);
trigger.on("event01", func02);
trigger.on("event02", func02);
trigger.on("event03", func03);
// 触发事件
trigger.raiseEvent("event01");
trigger.raiseEvent("event02");
trigger.raiseEvent("event03");
// 注销事件
trigger.on("event01", nullptr);
// 再次触发
trigger.raiseEvent("event01");
trigger.raiseEvent("event02");
return 0;
}