简体   繁体   中英

In GoF Observer Pattern, why are the methods in derived class virtual?

In GoF observer pattern, the subject is

class Subject {
  public:
    virtual ~Subject();
    virtual void Attach(Observer*);
    virtual void Detach(Observer*);
    virtual void Notify();
  protected:
    Subject();
  private:
    List<Observer*> *_observers;
};

and the concrete subject ClockTimer is given as

class ClockTimer : public Subject {
  public:
    ClockTimer();
    virtual int GetHour();
    virtual int GetMinute();
    virtual int GetSecond();
    void Tick();
};

I understand Subject is abstract therefore all methods are virtual . But why are the methods of ClockTimer virtual? It's not an abstract class after all.

As cppreference says :

Virtual functions are member functions whose behavior can be overridden in derived classes . As opposed to non-virtual functions, the overriding behavior is preserved even if there is no compile-time information about the actual type of the class. That is to say, if a derived class is handled using pointer or reference to the base class, a call to an overridden virtual function would invoke the behavior defined in the derived class. Such a function call is known as virtual function call or virtual call.

So GoF has used virtual functions to override behaviour in derived classes.

The only method that must be virtual in the Observer pattern is Observer::update . In the following code, SubjectBase can correctly be used as a base class for a concrete subject (eg ClockTimer ) since the constructor and destructor are protected. The "state" methods of the concrete subject (eg GetHour ) do not need to be virtual.

Since SubjectBase is non-virtual, the final specifier cannot be used. This allows derived classes to define different behavior for the fundamental methods (ie attach , detach , and notify ). Unless there are pressing performance considerations, it is preferable to implement Subject as a polymorphic class. Lastly, I see no fundamental reason to define the constructor as protected when Subject is a polymorphic class.

#include <list>

class Observer {
public:
    virtual ~Observer() = default;
    virtual void update() = 0;
};

class ConcreteObserver : public Observer {
public:
    void update() override;
};

class SubjectBase {
public:
    void attach(Observer* o);
    void detach(Observer* o);
    void notify();

protected:
    SubjectBase() = default;
    ~SubjectBase() = default;
private:
    std::list<Observer*> m_observers;
};

class Subject {
public:
    Subject() = default;
    virtual ~Subject() = default;
    virtual void attach(Observer* o) final;
    virtual void detach(Observer* o) final;
    virtual void notify() final;

private:
    std::list<Observer*> m_observers;
};

class ConcreteSubject : public Subject {
public:
    struct State;
    State getState();
    void attach(Observer* o); // compile time error!
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM