Search code examples
design-patternsbridge

Bridge pattern - two examples comparison


I was wondering if both of examples (or neither of them) are bridge pattern. So the first one:

class ButtonImpl {
    public:
    virtual void click() = 0;
};

// concrete implementation
class ToggleButtonImpl : public ButtonImpl {
    public: 
    void click() {
        cout << "Push\n";
    }
};

// concrete implementation
class PushButtonImpl : public ButtonImpl {
    public: 
    void click() {
        cout << "Push\n";
        cout << "Pop\n";
    }
};

// abstraction
class Button {
    public: 
    Button(ButtonImpl* buttonImpl) : m_buttonImpl{ buttonImpl }
    {
    }
    void click() {
        m_buttonImpl->click();
    }
    
    private: 
    ButtonImpl* m_buttonImpl;
};

and the second one:

// implementation
class ButtonImpl {
    public:
    virtual void click() = 0;
};

// concrete implementation
class WindowsButtonImpl : public ButtonImpl {
    public:
    void click() { cout << "windows system\n"; }
};

// concrete implementation
class LinuxButtonImpl : public ButtonImpl {
    public:
    void click() { cout << "linux system\n"; }
};

// abstraction
class Button {
    public:
    Button(ButtonImpl* buttonImpl) : m_buttonImpl{ buttonImpl } {}
    virtual void click() = 0;
    protected:
    ButtonImpl* m_buttonImpl;
};

// concrete abstraction
class ToggleButton : public Button {
    public: 
    ToggleButton(ButtonImpl* buttonImpl) : Button(buttonImpl) {};
    void click() {
        m_buttonImpl->click();
        if(state) {
            cout << "Push\n";
            state = 0;
        } else {
            cout << "Pop\n";
            state = 1;
        }
    }
    private:
    bool state;
};

// concrete abstraction
class PushButton : public Button {
    public: 
    PushButton(ButtonImpl* buttonImpl) : Button(buttonImpl) {};
    void click() {
        m_buttonImpl->click();
        cout << "Push\n";
        cout << "Pop\n";
    }
};

I'm constantly thinking that both examples are somehow correct with structure of this pattern, and in my opinion with its description. But I cannot find any proper exaplanation to answer this question.


Solution

  • The first example looks like plain old composition. Although the Button class is labelled as an abstraction, it is actually a concrete class; so concretion has a abstraction.

    In the Bridge Pattern, the "bridge" relationship is between two abstractions, where high-level abstraction has a low-level abstraction. That's what's portrayed in the second example.

    The terminology gets confusing, because what the pattern calls the "implementor" is also an abstraction: it's the low-level abstraction which the high-level abstraction uses in its implementations.

    A bridge connects two separate inheritance hierarchies using composition. The two hierarchies vary independently through separate sets of subclasses. The second example has two separate sets of subclasses. The first example does not.