C++ Adapter Pattern – How to Use ‘Adapter’ Without Changes in Existing Code

adaptercclass-designdesign-patternssolid

Here we have TV class and DVD class as example:

class TV
{
public:
    TV();
    virtual ~TV();

    void on() const;
    void off() const;
};

class DVDPlayer
{
public:
    DVDPlayer();
    ~DVDPlayer();

    void SetCD() const;
    void StartPlay() const;
    void Eject() const;
    void PowerOff() const;
};

We create Adapter which helps DVD to "pretends" TV:

class TVStyleAdapter :
    public TV
{
public:
    TVStyleAdapter(DVDPlayer* AdapteeDVD);
    ~TVStyleAdapter();

    void on() const;
    void off() const;

private:
    DVDPlayer* DVD;
};

// override base class funcs:
void TVStyleAdapter::on() const
{
    DVD->SetCD();
    DVD->StartPlay();
}

void TVStyleAdapter::off() const
{
    DVD->Eject();
    DVD->PowerOff();
}

After that I can add "virtual" in the TV(Base) class & override on() off() functions in Adapter class. And it will be works right.

BUT the questions is:

  1. Can we somehow create an Adapter without ANY changes (e.g. adding "virtual") in a base ('TV') class?
  2. Is it possible in this situation not violate the Open Closed
    principle?
  3. If I assume using an adapter in my program
    in the future, should I do the virtual methods in my classes in
    advance?

Best Answer

1. Yes, but no:

You could compile any code with a TVStyleAdapter instead of a TV, and it would work without a change in TV. So in a certain sense, the answer could be yes.

But this compile-time reuse of the interface would also work if TVStyleAdapter would be unrelated to TV. Unfortunately, it's no dynamic: you have to know the real object type at compile time, and you couldn't hope for a dynamic, object dependent behavior at runtime.

If you want polymorphism, i.e. use a pointer or a reference to a TV base class and expect the correct behavior to happen depending on the real type of the object you must have the virtual in the base class.

2. Yes, but who broke the principle ?

The question is not so much whether have to change the base change the base class, but rather why the base class was not already virtual.

You think that you break the close principle because you have to add the virtual in the base class. But in reality the designer of the base class broke the open principle in the first line.

3. Design for polymorphism from the beginning

If you want a class to be polymorphic, that is behave differently at rutime depending on its real type, you have to design it accordingly from the start. SO yes, virtual in advance (and consequently a virtual destructor, even if it remains empty)