观察者模式
扩展:观察者模式——委托
C++
参考:https://www.cnblogs.com/Galesaur-wcy/p/15905936.html
#include <iostream>
#include <list>
#include <memory>
#include <string>
using namespace std;
// Observer类 抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口要做更新接口。
// 观察者一般用一个抽象类或者接口实现,更新接口通常包含一个Update()方法 这个方法叫做更新方法。
class Observer
{
public:
virtual void Update(int) = 0;
virtual ~Observer() = default;
virtual void SetName(const string &observerName) final
{
m_observerName = observerName;
}
virtual string GetName() const final
{
return m_observerName;
}
protected:
string m_observerName;
};
// Subject类 可翻译为主题或抽象通知者 一般用一个抽象类或者一个接口实现。他把所有对观察者对象的引用保存
// 在一个聚集里,每个主题都可以又任何数量的观察者。抽象主题提供一个接口,可增加或者删除观察者对象
class Subject
{
public:
virtual void Attach(shared_ptr<Observer>) = 0;
virtual void Detach(shared_ptr<Observer>) = 0;
virtual void Notify() = 0;
};
// ConcreteObserver 具体观察者 实现抽象观察角色所要求的更新接口,以便使本身的状态与主题的状态相协调.
// 具体观察者角色可以保存一个指向具体主题对象的引用.具体观察者校色通常用一个具体子类实现
class ConcreteObserver : public Observer
{
public:
ConcreteObserver(shared_ptr<Subject> pSubject, const string &observerName)
: m_pSubject(pSubject)
{
m_observerName = observerName;
}
void Update(int value) override
{
cout << " ConcreteObserver " << m_observerName << " gets the update. New State: " << value << endl;
}
private:
shared_ptr<Subject> m_pSubject;
};
class ConcreteObserver2 : public Observer
{
public:
ConcreteObserver2(shared_ptr<Subject> pSubject, const string &observerName)
: m_pSubject(pSubject)
{
m_observerName = observerName;
}
void Update(int value) override
{
cout << " ConcreteObserver2 " << m_observerName << " gets the update. New State: " << value << endl;
}
private:
shared_ptr<Subject> m_pSubject;
};
// ConcreteSubject类,叫做具体主题或者具体通知者..将有关状态存入具体观察者对象;在具体主题内部状态改变时...给所有登记过的观察者发出通知.
// 具体主题对象通常用一个具体子类实现.
class ConcreteSubject : public Subject
{
public:
void Attach(shared_ptr<Observer> pObserver)
{
m_ObserverList.push_back(pObserver);
}
void Detach(shared_ptr<Observer> pObserver)
{
m_ObserverList.remove_if([=](const shared_ptr<Observer> &observer)
{ return observer == pObserver; });
}
void Notify()
{
for (const auto &observer : m_ObserverList)
{
cout << " Notifying -> " << observer->GetName() << endl;
observer->Update(m_iState);
}
}
void SetState(int state)
{
cout << "State changed to " << state << endl;
m_iState = state;
}
private:
list<shared_ptr<Observer>> m_ObserverList;
int m_iState;
};
int main()
{
auto pSubject = make_shared<ConcreteSubject>();
auto pObserver = make_shared<ConcreteObserver>(pSubject, "observer1");
auto pObserver2 = make_shared<ConcreteObserver2>(pSubject, "observer2");
pSubject->Attach(pObserver);
pSubject->Attach(pObserver2);
pSubject->SetState(2);
pSubject->Notify();
cout << endl;
pSubject->Detach(pObserver);
pSubject->SetState(3);
pSubject->Notify();
cout << endl;
return 0;
}
C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct Subject Subject;
typedef struct Observer
{
char *name;
void (*update)(struct Subject *, int, void *);
} Observer;
typedef struct Subject
{
struct Observer **observers;
size_t observer_count;
int state;
} Subject;
void ConcreteObserverUpdate(struct Subject *subject, int value, void *data)
{
printf(" ConcreteObserver get the update. New State: %d\n", value);
}
void ConcreteObserver2Update(struct Subject *subject, int value, void *data)
{
printf(" ConcreteObserver2 get the update. New State: %d\n", value);
}
void attach(struct Subject *subject, Observer *observer)
{
Observer **newObservers = realloc(subject->observers, sizeof(Observer *) * (subject->observer_count + 1));
if (newObservers == NULL)
{
fprintf(stderr, "Memory allocation failed.\n");
exit(EXIT_FAILURE);
}
newObservers[subject->observer_count++] = observer;
subject->observers = newObservers;
}
void detach(struct Subject *subject, Observer *observer)
{
bool removed = false;
int i;
for (i = 0; i < subject->observer_count; ++i)
{
if (subject->observers[i] == observer)
{
subject->observer_count--;
removed = true;
int j;
for (j = i; j < subject->observer_count; ++j)
{
subject->observers[j] = subject->observers[j + 1];
}
break;
}
}
if (!removed)
{
fprintf(stderr, "Observer not found.\n");
}
}
void notify(struct Subject *subject)
{
int i;
for (i = 0; i < subject->observer_count; ++i)
{
printf(" Notifying -> %s\n", subject->observers[i]->name);
subject->observers[i]->update(subject, subject->state, subject->observers[i]);
}
}
void setState(struct Subject *subject, int state)
{
printf("state changed......\n");
subject->state = state;
}
void safe_free(void *ptr)
{
if (ptr)
free(ptr);
}
int main()
{
Subject *pSubject = (Subject *)malloc(sizeof(Subject));
pSubject->observers = NULL;
pSubject->observer_count = 0;
pSubject->state = 0;
Observer observer1 = {
.name = strdup("observer1"),
observer1.update = ConcreteObserverUpdate,
};
Observer observer2 = {
.name = strdup("observer2"),
.update = ConcreteObserver2Update,
};
attach(pSubject, &observer1);
attach(pSubject, &observer2);
setState(pSubject, 2);
notify(pSubject);
printf("\n");
detach(pSubject, &observer1);
setState(pSubject, 3);
notify(pSubject);
printf("\n");
safe_free(observer1.name);
safe_free(observer2.name);
safe_free(pSubject->observers);
safe_free(pSubject);
return 0;
}