カテゴリー
C++

C++ Observer Pattern

C++でObserver, Subjectパターンを使ってCustom Listenerを作るサンプルコード

class CustomSubjectInterface {
public:
  class Listener {
  public:
    virtual ~Listener() {}
    virtual void onUpdated(CustomSubjectInterface* subject) = 0;
  };
  virtual ~CustomSubjectInterface() {}
  virtual void addListener(Listener* listener) = 0;
  virtual void removeListener(Listener* listener) = 0;
  virtual void notifyListeners(CustomSubjectInterface* subject) = 0;
};

class BoolSubject: public CustomSubjectInterface {
public:
  
  enum StatusCode {
    Success, Error
  };
  
  void addListener(CustomSubjectInterface::Listener* listener) override
  {
    listeners_.push_back(listener);
  }

  void removeListener(CustomSubjectInterface::Listener* listener) override
  {
    listeners_.erase(std::remove(listeners_.begin(), listeners_.end(), listener),listeners_.end());
  }

  void notifyListeners(CustomSubjectInterface* subject) override
  {
    for (CustomSubjectInterface::Listener* listener : listeners_) {
      listener->onUpdated(subject);
    }
  }
  
  void toggle() {
    if(isTrue_) {
      isTrue_ = false;
    } else {
      isTrue_ = true;
    }
    notifyListeners(this);
  }
  
  bool& getIsTrue() {
    return isTrue_;
  }
  
  void addMessage(juce::StringRef m, StatusCode code) {
    message = m;
    code_ = code;
  }
  
  std::string getMessage() {
    return message;
  }
  
  StatusCode getStatusCode() {
    return code_;
  }
  
  void setNewVoicingId(int newId) {
    newVoicingId = newId;
  }
  
  int getNewVoicingId() {
    return newVoicingId;
  }
  
private:
  int newVoicingId = 0;
  StatusCode code_ = Success;
  bool isTrue_ = false;
  std::string message;
  std::vector<CustomSubjectInterface::Listener*> listeners_;
};

Listener側では以下のコードで変更を受け取れます。

void onUpdated(CustomSubjectInterface* subject) override {
  BoolSubject* boolSubject = dynamic_cast<BoolSubject*>(subject);
  if (boolSubject != nullptr) {
    // Do something with the boolSubject
    bool isTrue = boolSubject->getIsTrue();
    // ...
  }
}