“设计模式解释”中的桥梁模式示例

时间:2013-01-23 08:43:53

标签: c++ oop design-patterns bridge

我正在研究“设计模式解释”中的桥梁模式示例。 我正在看的例子是例10.3,可以在

找到

http://www.netobjectives.com/resources/books/design-patterns-explained/cpp-code-examples/chapter10#10-3

我遇到的具体问题是Shape类及其派生类。

#pragma once
#include "Drawing.h"

class Shape
{
public:
    Shape(Drawing *aDrawing);
    virtual void draw()= 0;

protected:
    Drawing *myDrawing;
    void drawLine( double, double, double, double);
    void drawCircle( double, double, double);

public:
    ~Shape(void);
};

在Circle课程中我们有

#pragma once
#include "Shape.h"

class Circle : public Shape
{
public:
    Circle(Drawing*, double, double, double);
    virtual void draw();
    virtual void drawCircle(double, double, double)=0;

public:
    ~Circle(void);
protected:
    double _x, _y, _r;
};

所以我的问题是: 为什么drawCircle在继承类中是纯虚拟的,因为该方法实际上是在基类中实现的?

2 个答案:

答案 0 :(得分:4)

想象一下,您正在构建一个模块,使用不同的API(Windows GDI,一些智能手机API,OpenGL,任何东西)绘制形状。拥有典型的层次结构abstract Shape <--- concrete Circleabstract Shape <--- concrete Rectangle,您必须重新编译并重新部署Circle和{{ 1}}每次添加新框架时,每次在现有框架中发生变化时。这些更改甚至可能涉及修改这些类的构造函数,因此模块的用户也必须更改其代码。

示例:您的模块有第一个版本,Rectangle具有以下界面:

Circle

然后,其中一个平台的优化原因会促使您事先知道当前平台的class Circle : public Shape { public: Circle(int x, int y, int radius); void draw(...); }; 分辨率(在实际绘制圆圈之前)。所以,你必须改变构造函数:

DPI

您的代码的客户端必须重新编译他们的应用程序。当然会有一些黑客可以避免这种情况(比如引入class Circle : public Shape { public: Circle(int x, int y, int radius, int dpi); void draw(...); }; ),但它们会导致高度耦合且难以维护的代码。如果您使用桥接模式,您可以保持您的清晰设计完好无损并仍然表达您的域名(一般来说,“圈子”的概念不应该知道任何有关“dpi分辨率”的事情。)

所以:

CircleWithDpi

class Circle : public Shape
{
  public:
    Circle(int x, int y, int radius);

    virtual void draw(...) = 0;
};

class CircleImpl : public Circle
{
  public:
    CircleImpl(int x, int y, int radius, int dpi);
    //perform some calculations before drawing for optimization

    void draw(...);
    //draw using appropriate API
};

当然,您会有很多class ShapeFactory { public: virtual Circle* CreateCircle(int x, int y, int radius) = 0; }; 个 - 每个都适用于您的模块支持的不同平台(因此,CircleImplCircleImplGDICircleImplTk等。)

CircleImplOpenGL的实现中,您需要适当地创建一个特定的ShapeFactory,并且模块的客户端不必了解它。此示例是您指定链接的简化版本。请注意,现在,当一个可能的CircleImpl被用作CircleImpl时,没有抽象类被实例化,所以这也应该清除你关于抽象派生类的问题。

这种模式背后的主要思想是有两个抽象层次:Circle是一个抽象的几何概念,ShapeCircleRectangle更具体但是在绘制它们的许多技术可能性的背景下,它们仍然是非常抽象的。当您知道上下文时,会存在特定形状的具体表示:例如 - 在栅格上绘图或使用矢量图形。

另一个抽象层次使您可以推迟更多关于代码的决策 - 首先我们推迟决定我们的形状。然后,ShapeCircle我们推迟了如何绘制它们的决定。延期决策为我们提供了解耦的,灵活的代码(如“添加的DPI”示例所示)。

答案 1 :(得分:1)

只要您不尝试创建该类的实例,就可以在任何类中使用纯虚方法。