首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >“设计模式解释”中的桥接模式示例

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

Stack Overflow用户
提问于 2013-01-23 16:43:53
回答 2查看 4.3K关注 0票数 1

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

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

我特别困惑的是Shape类及其派生类。

代码语言:javascript
复制
#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类中,我们有

代码语言:javascript
复制
#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在继承的类中可以是纯虚的呢?

EN

回答 2

Stack Overflow用户

发布于 2013-09-15 18:27:17

想象一下,你正在构建一个使用不同API (windows GDI,一些智能手机API,OpenGL,任何东西)绘制形状的模块。对于典型的层次结构、<--- concrete Circleabstract Shape <--- concrete Rectangle,每次添加新框架以及现有框架中的某些更改时,都必须重新编译和重新部署CircleRectangle。这样的更改甚至可能涉及修改这些类的构造函数,因此模块的用户也必须更改他们的代码。

示例:您有一个可以正常工作的模块的第一个版本,具有用于Circle的以下接口

代码语言:javascript
复制
class Circle : public Shape
{
  public:
    Circle(int x, int y, int radius);

    void draw(...);
};

然后,由于某个平台的优化原因,你不得不提前知道当前平台的DPI分辨率(在实际绘制圆圈之前)。因此,您必须更改构造函数:

代码语言:javascript
复制
class Circle : public Shape
{
  public:
    Circle(int x, int y, int radius, int dpi);

    void draw(...);
};

而你的代码的客户将不得不重新编译他们的应用程序。当然,有一些黑客可以避免这一点(比如引入CircleWithDpi),但它们将导致高度耦合和难以维护的代码。如果你使用桥模式,你可以保持清晰的设计,同时仍然表达你的领域(一般来说,“圆”的概念不应该知道任何关于"dpi分辨率“的东西)。

因此,拥有:

代码语言:javascript
复制
class Circle : public Shape
{
  public:
    Circle(int x, int y, int radius);

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

代码语言:javascript
复制
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
};

代码语言:javascript
复制
class ShapeFactory
{
  public:
    virtual Circle* CreateCircle(int x, int y, int radius) = 0;
};

当然,您会有许多CircleImpl-每个都对应于您的模块支持的不同平台(so、CircleImplGDICircleImplTkCircleImplOpenGL等)。

ShapeFactory的实现中,您将适当地创建一个特定的CircleImpl,并且您的模块的客户端不必知道任何关于它的信息。此示例是您提供的链接的简化版本。注意,现在,当可能的CircleImpl之一被用作Circle时,没有抽象类被实例化,所以这也应该解决您关于抽象派生类的问题。

此模式背后的主要思想是具有两个级别的抽象:Shape是一个抽象的几何概念,CircleRectangleShape更具体,但在绘制它们的许多技术可能性的上下文中,它们仍然相当抽象。当你知道上下文时,特定形状的具体表示就存在了:例如,在光栅上绘图或使用矢量图形。

另一层抽象让你有可能推迟更多关于你的代码的决定--首先,我们推迟了关于我们拥有的形状的决定。然后,有了CircleRectangle,我们推迟了如何绘制它们的决定。延迟决策为我们提供了解耦的、灵活的代码(如“添加的DPI”示例所示)。

票数 4
EN

Stack Overflow用户

发布于 2013-01-23 16:48:44

纯虚方法在任何类中都是允许的,只要您不尝试创建该类的实例。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14475513

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档