面试题答案
一键面试桥接模式原理
桥接模式将抽象部分与它的实现部分分离,使它们都可以独立地变化。在C++中,通过抽象类和指针(或引用)来实现这种分离。抽象类定义了抽象接口,而实现部分由另一个抽象类及其派生类负责,抽象类持有实现部分的指针,从而将抽象与实现解耦。
桥接模式优势
- 解耦抽象和实现:使得抽象和实现可以独立演化,互不影响。
- 提高可扩展性:新增抽象或实现都比较容易,只需添加对应的派生类。
- 增强可维护性:由于抽象和实现分离,修改其中一方不会影响另一方。
C++ 代码实现
#include <iostream>
#include <string>
// 抽象绘制方式类
class DrawAPI {
public:
virtual void drawCircle(float x, float y, float radius) = 0;
virtual ~DrawAPI() {}
};
// 具体绘制到屏幕的实现
class DrawOnScreen : public DrawAPI {
public:
void drawCircle(float x, float y, float radius) override {
std::cout << "Drawing Circle[ on screen: x=" << x << ", y=" << y << ", radius=" << radius << "]" << std::endl;
}
};
// 具体绘制到文件的实现
class DrawToFile : public DrawAPI {
public:
void drawCircle(float x, float y, float radius) override {
std::cout << "Drawing Circle[ to file: x=" << x << ", y=" << y << ", radius=" << radius << "]" << std::endl;
}
};
// 抽象图形类
class Shape {
protected:
DrawAPI* drawAPI;
public:
Shape(DrawAPI* drawAPI) : drawAPI(drawAPI) {}
virtual void draw() = 0;
virtual ~Shape() { delete drawAPI; }
};
// 圆形类
class Circle : public Shape {
private:
float x, y, radius;
public:
Circle(float x, float y, float radius, DrawAPI* drawAPI) : Shape(drawAPI), x(x), y(y), radius(radius) {}
void draw() override {
drawAPI->drawCircle(x, y, radius);
}
};
// 矩形类
class Rectangle : public Shape {
private:
float x, y, width, height;
public:
Rectangle(float x, float y, float width, float height, DrawAPI* drawAPI) : Shape(drawAPI), x(x), y(y), width(width), height(height) {}
void draw() override {
// 假设这里有绘制矩形的逻辑
std::cout << "Drawing Rectangle[ x=" << x << ", y=" << y << ", width=" << width << ", height=" << height << "]" << std::endl;
drawAPI->drawCircle(x, y, 0); // 这里只是简单调用drawAPI示例,实际应绘制矩形
}
};
优化代码提高可扩展性和可维护性
- 新增图形类型:
- 定义新的图形类,继承自
Shape
抽象类。 - 实现
draw
方法,根据新图形的特性调用drawAPI
的方法。例如,新增三角形类:
- 定义新的图形类,继承自
class Triangle : public Shape {
private:
float x1, y1, x2, y2, x3, y3;
public:
Triangle(float x1, float y1, float x2, float y2, float x3, float y3, DrawAPI* drawAPI) : Shape(drawAPI), x1(x1), y1(y1), x2(x2), y2(y2), x3(x3), y3(y3) {}
void draw() override {
// 假设这里有绘制三角形的逻辑
std::cout << "Drawing Triangle[ x1=" << x1 << ", y1=" << y1 << ", x2=" << x2 << ", y2=" << y2 << ", x3=" << x3 << ", y3=" << y3 << "]" << std::endl;
drawAPI->drawCircle(x1, y1, 0); // 这里只是简单调用drawAPI示例,实际应绘制三角形
}
};
- 新增绘制方式:
- 定义新的
DrawAPI
派生类,实现drawCircle
等方法(如果有其他图形绘制方法也需实现)。 - 在需要使用新绘制方式的图形类构造函数中,可传入新的
DrawAPI
派生类对象。例如,新增绘制到打印机的方式:
- 定义新的
class DrawToPrinter : public DrawAPI {
public:
void drawCircle(float x, float y, float radius) override {
std::cout << "Drawing Circle[ to printer: x=" << x << ", y=" << y << ", radius=" << radius << "]" << std::endl;
}
};
然后在使用处,比如main
函数中:
int main() {
Shape* circle1 = new Circle(100, 100, 50, new DrawOnScreen());
circle1->draw();
delete circle1;
Shape* circle2 = new Circle(200, 200, 30, new DrawToFile());
circle2->draw();
delete circle2;
Shape* triangle = new Triangle(10, 10, 50, 10, 30, 50, new DrawToPrinter());
triangle->draw();
delete triangle;
return 0;
}
通过这种方式,新增图形类型或绘制方式都不会对现有代码造成较大影响,提高了代码的可扩展性和可维护性。