/*Shape_Bridge.cpp Example for Bridge Pattern (GoF) Feza BUZLUCA, Lecture Notes */ #include using std::cout; using std::endl; /* DP1 and DP2 are external drawing programs */ class DP1 { // First drawing program public: void static draw_a_line(double x1, double y1, double x2, double y2) { cout << "DP1: Line from " << x1 << "," << y1 << " to " << x2 << "," << y2 << endl; } void static draw_a_circle(double x, double y, double r) { cout << "DP1: Circle with the center " << x << "," << y << " and radius " << r << endl; } }; class DP2 { // Second drawing program public: void static drawline(double x1, double x2, double y1, double y2) { cout << "DP2: Line from " << x1 << "," << y1 << " to " << x2 << "," << y2 << endl; } void static drawcircle(double x, double y, double r) { cout << "DP2: Circle with the center " << x << "," << y << " and radius " << r << endl; } }; /* Adapters to access the external drawing programs (implementation) */ class Drawing { // Abstract base class of adapters public: virtual void drawLine(double, double, double, double) = 0; virtual void drawCircle(double, double, double) = 0; }; class V1Drawing : public Drawing { // Adapter for DP1 public: void drawLine(double x1, double y1, double x2, double y2); void drawCircle(double x, double y, double r); }; void V1Drawing::drawLine(double x1, double y1, double x2, double y2) { DP1::draw_a_line(x1, y1, x2, y2); // Access to DP1 } void V1Drawing::drawCircle(double x, double y, double r) { DP1::draw_a_circle(x, y, r); } class V2Drawing : public Drawing { // Adapter for DP2 public: void drawLine(double x1, double y1, double x2, double y2); void drawCircle(double x, double y, double r); }; void V2Drawing::drawLine(double x1, double y1, double x2, double y2) { DP2::drawline(x1, x2, y1, y2); // Access to DP2 } void V2Drawing::drawCircle(double x, double y, double r) { DP2::drawcircle(x, y, r); } /* Shapes (Abstraction) */ class Shape { // Abstract base class of Shapes public: Shape(Drawing *); // Constructor: Parameter is pointer to a drawing program (Adapter) virtual void draw() = 0; protected: void drawLine(double, double, double, double); void drawCircle(double, double, double); private: Drawing *drawProg; // Pointer to the related adapter of a drawing program (bridge) }; Shape::Shape(Drawing* dp) : drawProg{dp} // Constructor: Connection to the related implementation {} void Shape::drawLine(double x1, double y1, double x2, double y2){ drawProg->drawLine(x1, y1, x2, y2); // Currently connected drawing program is used } void Shape::drawCircle(double x, double y, double r){ drawProg->drawCircle(x, y, r); } /* Concrete shape classes */ // Rectangle class Rectangle : public Shape{ public: Rectangle(Drawing *, double, double, double, double); void draw(); private: double m_x1, m_y1, m_x2, m_y2; }; Rectangle::Rectangle(Drawing* dp, double x1, double y1, double x2, double y2) : Shape{ dp }, m_x1{x1}, m_x2{ x2 }, m_y1{ y1 }, m_y2{ y2 } {} void Rectangle::draw() { drawLine(m_x1, m_y1, m_x2, m_y1); // drawLine is inherited fro the Base class Shape drawLine(m_x2, m_y1, m_x2, m_y2); drawLine(m_x2, m_y2, m_x1, m_y2); drawLine(m_x1, m_y2, m_x1, m_y1); } // Circle class Circle : public Shape{ public: Circle(Drawing *, double, double, double); void draw(); private: double m_x, m_y, m_r; }; Circle::Circle(Drawing *dp, double x, double y, double r) : Shape(dp), m_x{ x }, m_y{ y }, m_r{r} {} void Circle::draw() { drawCircle(m_x, m_y, m_r); // drawCircle is inherited fro the Base class Shape } /* The Client (user) class that uses the Shapes library written for testing purposes */ class Client{ public: Client(Shape* inputShape) : m_shapePtr{ inputShape } //Initial shape to be used {} void setShape(Shape * inputShape) { //change current shape m_shapePtr = inputShape; } void operate(); // Responsibility of the Client private: Shape *m_shapePtr; // It can point to any type of Shape }; void Client::operate() { m_shapePtr->draw(); //The client does not know the type of the shape } /* The main function for testing purposes */ int main() { // Adapter objects for Drawing programs. In a real application, they will be created by the Factory. Drawing *dp1, *dp2; dp1 = new V1Drawing; dp2 = new V2Drawing; // Shape objects Rectangle* rectangle1 = new Rectangle{ dp1, 1, 1, 2, 2 }; // Rectangle1 uses dp1 Rectangle* rectangle2 = new Rectangle{ dp2, 10, 15, 20, 30 }; // Rectangle2 uses dp2 Circle* circle = new Circle{ dp2, 2, 2, 4 }; // Circle uses dp2 Client user{ rectangle1 }; //The client (user) will use the rectangle1 user.operate(); user.setShape(circle); //The client (user) will use the circle user.operate(); user.setShape(rectangle2); //The client (user) will use the rectangle2 user.operate(); delete rectangle1; delete rectangle2; delete circle; // Housekeeping delete dp1; delete dp2; return 0; }