设计模式---桥接模式

111 阅读4分钟

定义

桥接模式(Bridge Pattern)是一种结构型设计模式,用于将抽象部分与实现部分分离,使它们可以独立地变化。这种模式的主要目的是解耦,使得可以在不影响其他部分的情况下独立地改变接口和实现的各个方面。

结构

  • 抽象类(Abstraction) :定义了基于桥接接口的抽象部分。

  • 修正抽象类(RefinedAbstraction) :扩展了抽象类,可能增加新的功能或改变抽象类的行为。

  • 桥接接口(Implementor) :定义了实现部分的接口。通常这个接口相对简单。

  • 具体实现类(ConcreteImplementor) :实现了桥接接口,提供具体的实现。

实现步骤

  • 定义桥接接口:定义桥接接口和抽象部分的接口,确保它们之间的松耦合。

  • 实现具体的桥接类:实现桥接接口并提供具体的功能。

  • 创建抽象类:持有一个桥接接口的引用,通过该引用来调用具体实现。

  • 扩展抽象类:如有需要,扩展抽象类以提供更多功能。

代码示例

示例1

#include <iostream>
#include <memory>

// 桥接接口
class Implementor
{
public:
	virtual ~Implementor() = default;
	virtual void operationImpl() const = 0;
};


// 具体实现类A
class ConcreteImplementorA : public Implementor
{
public:
	void operationImpl() const override
	{
		std::cout << "ConcreteImplementorA operation" << std::endl;
	}
};


// 具体实现类B
class ConcreteImplementorB : public Implementor 
{
public:
	void operationImpl() const override 
	{
		std::cout << "ConcreteImplementorB operation" << std::endl;
	}
};


// 抽象类
class Abstraction
{
protected:
	std::unique_ptr<Implementor> implementor;

public:
	Abstraction(std::unique_ptr<Implementor> impl) : implementor(std::move(impl)) {}
	virtual ~Abstraction() = default;
	virtual void operation() const
	{
		implementor->operationImpl();
	}
};
 

// 扩展抽象类
class RefinedAbstraction : public Abstraction
{
public:
	RefinedAbstraction(std::unique_ptr<Implementor> impl) : Abstraction(std::move(impl)) {}

	void operation() const override 
	{
		std::cout << "RefinedAbstraction operation with ";
		Abstraction::operation();
	}
};


int main()
{
	// 使用 ConcreteImplementorA
	std::unique_ptr<Implementor> implA = std::make_unique<ConcreteImplementorA>();
	RefinedAbstraction abstractionA(std::move(implA));
	abstractionA.operation();

	// 使用 ConcreteImplementorB
	std::unique_ptr<Implementor> implB = std::make_unique<ConcreteImplementorB>();
	RefinedAbstraction abstractionB(std::move(implB));
	abstractionB.operation();

	system("pause");
	return 0;
}

示例2

假设开发一个绘图应用程序,支持不同类型的形状和不同的绘图工具。希望能够独立地添加新形状或新绘图工具,而不影响其他部分的代码。可以使用桥接模式来实现这一点。

  • 形状(Abstraction) :定义形状的接口,例如 Shape

  • 具体形状(RefinedAbstraction) :实现具体的形状,例如 CircleRectangle

  • 绘图工具(Implementor) :定义绘图工具的接口,例如 DrawingAPI

  • 具体绘图工具(ConcreteImplementor) :实现具体的绘图工具,例如 OpenGLDrawingAPIDirectXDrawingAPI

#include <iostream>
#include <memory>

// 绘图工具接口
class DrawingAPI {
public:
    virtual ~DrawingAPI() = default;
    virtual void drawCircle(double x, double y, double radius) const = 0;
    virtual void drawRectangle(double x, double y, double width, double height) const = 0;
};

// 具体绘图工具A
class OpenGLDrawingAPI : public DrawingAPI {
public:
    void drawCircle(double x, double y, double radius) const override {
        std::cout << "OpenGL: Drawing circle at (" << x << ", " << y << ") with radius " << radius << std::endl;
    }

    void drawRectangle(double x, double y, double width, double height) const override {
        std::cout << "OpenGL: Drawing rectangle at (" << x << ", " << y << ") with width " << width << " and height " << height << std::endl;
    }
};

// 具体绘图工具B
class DirectXDrawingAPI : public DrawingAPI {
public:
    void drawCircle(double x, double y, double radius) const override {
        std::cout << "DirectX: Drawing circle at (" << x << ", " << y << ") with radius " << radius << std::endl;
    }

    void drawRectangle(double x, double y, double width, double height) const override {
        std::cout << "DirectX: Drawing rectangle at (" << x << ", " << y << ") with width " << width << " and height " << height << std::endl;
    }
};

// 形状接口
class Shape {
protected:
    std::shared_ptr<DrawingAPI> drawingAPI;

public:
    Shape(std::shared_ptr<DrawingAPI> api) : drawingAPI(api) {}
    virtual ~Shape() = default;
    virtual void draw() const = 0;
};

// 具体形状A
class Circle : public Shape {
private:
    double x, y, radius;

public:
    Circle(double x, double y, double radius, std::shared_ptr<DrawingAPI> api)
        : Shape(api), x(x), y(y), radius(radius) {}

    void draw() const override {
        drawingAPI->drawCircle(x, y, radius);
    }
};

// 具体形状B
class Rectangle : public Shape {
private:
    double x, y, width, height;

public:
    Rectangle(double x, double y, double width, double height, std::shared_ptr<DrawingAPI> api)
        : Shape(api), x(x), y(y), width(width), height(height) {}

    void draw() const override {
        drawingAPI->drawRectangle(x, y, width, height);
    }
};

int main() {
    // 使用 OpenGL 绘图工具
    std::shared_ptr<DrawingAPI> openglAPI = std::make_shared<OpenGLDrawingAPI>();
    Circle openglCircle(5.0, 10.0, 3.0, openglAPI);
    Rectangle openglRectangle(1.0, 2.0, 4.0, 5.0, openglAPI);

    openglCircle.draw();
    openglRectangle.draw();

    // 使用 DirectX 绘图工具
    std::shared_ptr<DrawingAPI> directxAPI = std::make_shared<DirectXDrawingAPI>();
    Circle directxCircle(5.0, 10.0, 3.0, directxAPI);
    Rectangle directxRectangle(1.0, 2.0, 4.0, 5.0, directxAPI);

    directxCircle.draw();
    directxRectangle.draw();

    return 0;
}
  • 绘图工具接口 (DrawingAPI)

    • 定义了绘制不同形状的接口。具体的绘图工具(如 OpenGL 和 DirectX)实现了这个接口。
  • 具体绘图工具 (OpenGLDrawingAPIDirectXDrawingAPI)

    • 提供了具体的绘图实现。这些类不关心形状的具体细节,只知道如何绘制形状。
  • 形状接口 (Shape)

    • 持有一个 DrawingAPI 的引用,并定义了一个 draw 方法,用于绘制形状。
  • 具体形状 (CircleRectangle)

    • 实现了 Shape 接口,并使用 DrawingAPI 的方法来绘制自己。
  • 客户端代码

    • 创建了不同的 Shape 对象和 DrawingAPI 对象,通过不同的绘图工具来绘制不同的形状。

总结

  • 解耦:形状和绘图工具是解耦的。可以独立地添加新的形状或新的绘图工具。

  • 灵活性:可以在运行时选择不同的绘图工具,绘制不同类型的形状。

  • 扩展性:添加新的形状或绘图工具不会影响现有的代码,只需添加新的类和实现。