MST

星途 面试题库

面试题:C++抽象类在桥接模式中的应用与优化

解释桥接模式在C++中的原理和优势。假设你正在设计一个图形绘制系统,有不同类型的图形(如圆形、矩形)和不同的绘制方式(如绘制在屏幕上、绘制到文件中),请使用C++抽象类实现桥接模式,并说明如何优化代码以提高可扩展性和可维护性,比如如何处理新增图形类型或绘制方式。
19.5万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

桥接模式原理

桥接模式将抽象部分与它的实现部分分离,使它们都可以独立地变化。在C++中,通过抽象类和指针(或引用)来实现这种分离。抽象类定义了抽象接口,而实现部分由另一个抽象类及其派生类负责,抽象类持有实现部分的指针,从而将抽象与实现解耦。

桥接模式优势

  1. 解耦抽象和实现:使得抽象和实现可以独立演化,互不影响。
  2. 提高可扩展性:新增抽象或实现都比较容易,只需添加对应的派生类。
  3. 增强可维护性:由于抽象和实现分离,修改其中一方不会影响另一方。

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示例,实际应绘制矩形
    }
};

优化代码提高可扩展性和可维护性

  1. 新增图形类型
    • 定义新的图形类,继承自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示例,实际应绘制三角形
    }
};
  1. 新增绘制方式
    • 定义新的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;
}

通过这种方式,新增图形类型或绘制方式都不会对现有代码造成较大影响,提高了代码的可扩展性和可维护性。