1、什么是观察者模式?
观察者模式,又称 “发布-订阅” (Publish-Subscribe)模式。
观察者模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主体对象。这个主体对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
2、为何要使用观察者模式?
1、为了解耦。让耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化。同时也满足"依赖倒转" 原则:让程序都依赖抽象,而不是相互依赖。
2、使用观察者模式的动机:
将一个系统分割成一系列互相协作的类有一个很不好的副作用:需要维护相关对象间的一致性。
我们不希望为了维护一致性而使得各类紧密耦合,这样,会给维护、扩展和重用都带来不便。
3、使用场景
(1)当一个对象的改变需要同时改变其他对象,且他不知道具体有多少个对象有待改变时,应该考虑使用观察者模式。
(2)换言之,一个抽象模型有两个方面,其中一方面依赖于另一方面,此时,用观察者模式可以将这两者凡转载独立的对象中,使他们各自独立地改变和复用。
3、如何才能用好观察者模式?
需要练习。。。
4、怎样使用观察者模式?
4.1 观察者模式的演进
- 双向耦合
- 单向解耦(解耦 具体观察者与 通知者)
- 双向解耦(解耦 具体观察者 与 具体通知者)
(1)ISubject类:把所有观察者对象的引用(或指针),保存在一个聚集里,每个主题都可以有任何数量的观察者。 抽象主题提供一个接口,可以增加和删除观察者对象。
(2)IObserver类:抽象观察者,为所有具体观察者定义一个接口,在得到主题的通知时,更新自己。
(3)ConcreteSubject类:具体主题,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
(4)ConcreteObserver类:具体观察者,实现抽象观察者角色所要求的更新接口,一遍使本身的状态与主题的状态相协调/一致。
5、实例
1、双向耦合
1.1.1 Secretary.h
#pragma once
#include <list>
#include <string>
#include "StockObserver.h"
using namespace std;
class StockObserver;
class Secretary
{
public:
Secretary();
Secretary(const string& act) :m_sAction(act) {}
~Secretary();
public:
//增加
void attach(StockObserver* observer);
//通知
void notify();
//前台状态
string getAction();
void setAction(const string& _action);
private:
//同事列表
list<StockObserver* > m_observers;
//前台状态
string m_sAction;
};
1.1.2 Secretary.cpp
#include "Secretary.h"
Secretary::Secretary()
{
}
Secretary::~Secretary()
{
}
void Secretary::attach(StockObserver* observer)
{
m_observers.push_back(observer);
}
void Secretary::notify()
{
for each (StockObserver* observer in m_observers)
{
observer->update();
}
}
std::string Secretary::getAction()
{
return m_sAction;
}
void Secretary::setAction(const string& _action)
{
m_sAction = _action;
}
1.2.1 StockObserver.h
#pragma once
#include <list>
#include <string>
#include "Secretary.h"
using namespace std;
class Secretary;
class StockObserver
{
public:
StockObserver();
StockObserver(const string& name, Secretary* sub);
void update();
private:
string m_name;
Secretary* m_sub;
};
1.2.2 StockObserver.cpp
#include "StockObserver.h"
#include <iostream>
StockObserver::StockObserver()
{
}
StockObserver::StockObserver(const string& name, Secretary* sub)
: m_name(name), m_sub(sub)
{
}
void StockObserver::update()
{
//err: getAction没起作用,不知道原因!!
//还真是需要指针,指针指的对象永远可以知晓
cout << m_sub->getAction() << "," << m_name << ", 关闭股票行情,继续工作!" << endl;
}
1.3 main.cpp
#include<iostream>
#include "Secretary.h"
#include "StockObserver.h"
int main()
{
Secretary* pSecretary = new Secretary();
StockObserver* pObserver1 = new StockObserver("小白", pSecretary);
StockObserver* pObserver2 = new StockObserver("小黄", pSecretary);
pSecretary->attach(pObserver1);
pSecretary->attach(pObserver2);
pSecretary->setAction("老板回来了");
pSecretary->notify();
//析构指针对象
delete pSecretary;
pSecretary = nullptr;
delete pObserver1;
pObserver1 = nullptr;
delete pObserver2;
pObserver2 = nullptr;
system("pause");
return 0;
}
//此种模式,
//双向耦合(Secretary依赖StockObserver,且StockObserver同时也依赖Secretary),不好!!
2、单向解耦(解耦 具体观察者与 通知者)
2.1.1 IObserver.h
#pragma once
#include <list>
#include <string>
#include "Secretary.h"
class Secretary;
using namespace std;
class IObserver
{
public:
IObserver();
IObserver(const string& name, Secretary* sub);
virtual void update() = 0;
protected:
string m_name;
Secretary* m_sub;
};
2.1.2 IObserver.cpp
#include "IObserver.h"
IObserver::IObserver()
{
}
IObserver::IObserver(const string& name, Secretary* sub)
:m_name(name), m_sub(sub)
{
}
2.2.1 StockObserver.h
#pragma once
#include <list>
#include <string>
#include "IObserver.h"
using namespace std;
class Secretary;
class StockObserver :public IObserver
{
public:
StockObserver();
StockObserver(const string& name, Secretary* sub);
void update();
};
2.2.2 StockObserver.cpp
#include "StockObserver.h"
#include <iostream>
StockObserver::StockObserver()
{
}
StockObserver::StockObserver(const string& name, Secretary* sub)
: IObserver(name, sub)
{
}
void StockObserver::update()
{
//err: getAction没起作用,不知道原因!!
//还真是需要指针,指针指的对象永远可以知晓
cout << m_sub->getAction() << "," << m_name << ", 关闭股票行情,继续工作!" << endl;
}
2.3.1 NBAObserver.h
#pragma once
#include "IObserver.h"
class NBAObserver :
public IObserver
{
public:
NBAObserver();
NBAObserver(const string& name, Secretary* sub);
virtual void update() override;
};
2.3.2 NBAObserver.cpp
#include "NBAObserver.h"
#include <iostream>
NBAObserver::NBAObserver()
{
}
NBAObserver::NBAObserver(const string& name, Secretary* sub)
:IObserver(name, sub)
{
}
void NBAObserver::update()
{
cout << m_sub->getAction() << "," << m_name << ", 关闭NBA直播,继续工作!" << endl;
}
2.4.1 Secretary.h
#pragma once
#include <list>
#include <string>
#include "IObserver.h"
using namespace std;
class IObserver;
class Secretary
{
public:
Secretary();
Secretary(const string& act) :m_sAction(act) {}
public:
//增加
void attach(IObserver* observer);
void detach(IObserver* observer);
//通知
void notify();
//前台状态
string getAction();
void setAction(const string& _action);
private:
//同事列表
list<IObserver* > m_observers;
//前台状态
string m_sAction;
};
2.4.2 Secretary.cpp
#include "Secretary.h"
Secretary::Secretary()
{
}
void Secretary::attach(IObserver* observer)
{
m_observers.push_back(observer);
}
void Secretary::detach(IObserver* observer)
{
m_observers.remove(observer);
delete observer;
observer = nullptr;
}
void Secretary::notify()
{
for each (IObserver* observer in m_observers)
{
observer->update();
}
}
std::string Secretary::getAction()
{
return m_sAction;
}
void Secretary::setAction(const string& _action)
{
m_sAction = _action;
}
2.5 main.cpp
#include<iostream>
#include "Secretary.h"
#include "StockObserver.h"
#include "NBAObserver.h"
void test2()
{
cout << "==============test2()=================" << endl;
Secretary* pSecretary = new Secretary();
StockObserver* pObserver1 = new StockObserver("小白", pSecretary);
NBAObserver* pObserver2 = new NBAObserver("小黄", pSecretary);
pSecretary->attach(pObserver1);
pSecretary->attach(pObserver2);
pSecretary->setAction("Leo回来了");
pSecretary->notify();
//析构指针对象
delete pSecretary;
pSecretary = nullptr;
delete pObserver1;
pObserver1 = nullptr;
delete pObserver2;
pObserver2 = nullptr;
}
//此种模式,
//也存在耦合
//有一点改进:观察者稍稍解耦,可以拓展任意多个观察者
int main()
{
test2();
system("pause");
return 0;
}
3、双向解耦(解耦 具体观察者 与 具体通知者)
3.1.1 IObserver.h
#pragma once
#include <list>
#include <string>
#include "ISubject.h"
class ISubject;
using namespace std;
class IObserver
{
public:
IObserver();
IObserver(const string& name, ISubject* sub);
virtual void update() = 0;
protected:
string m_name;
ISubject* m_sub;
};
3.1.2 IObserver.cpp
#include "IObserver.h"
IObserver::IObserver()
{
}
IObserver::IObserver(const string& name, ISubject* sub)
:m_name(name), m_sub(sub)
{
}
3.2.1 StockObserver .h
#pragma once
#include <list>
#include <string>
#include "IObserver.h"
using namespace std;
class Secretary;
class StockObserver :public IObserver
{
public:
StockObserver();
StockObserver(const string& name, ISubject* sub);
void update()override;
};
3.2.2 StockObserver .cpp
#include "StockObserver.h"
#include <iostream>
StockObserver::StockObserver()
{
}
StockObserver::StockObserver(const string& name, ISubject* sub)
: IObserver(name, sub)
{
}
void StockObserver::update()
{
//err: getAction没起作用,不知道原因!!
//还真是需要指针,指针指的对象永远可以知晓
cout << m_sub->getAction() << "," << m_name << ", 关闭股票行情,继续工作!" << endl;
}
3.3.1 NBAObserver .h
#pragma once
#include "IObserver.h"
class NBAObserver :
public IObserver
{
public:
NBAObserver();
NBAObserver(const string& name, ISubject* sub);
virtual void update() override;
};
3.3.1 NBAObserver .cpp
#include "NBAObserver.h"
#include <iostream>
NBAObserver::NBAObserver()
{
}
NBAObserver::NBAObserver(const string& name, ISubject* sub)
:IObserver(name, sub)
{
}
void NBAObserver::update()
{
cout << m_sub->getAction() << "," << m_name << ", 关闭NBA直播,继续工作!" << endl;
}
3.4 ISubject.h
#pragma once
#include "IObserver.h"
#include <string>
using namespace std;
class IObserver;
class ISubject
{
public:
virtual void attach(IObserver* observer) = 0;
virtual void detach(IObserver* observer) = 0;
virtual void notify() = 0;
virtual string getAction() = 0;
virtual void setAction(const string& action) = 0;
};
3.5.1 Secretary.h
#pragma once
#include "ISubject.h"
#include <list>
class IObserver;
class Secretary :public ISubject
{
public:
Secretary();
Secretary(const string& act) :m_sAction(act) {}
public:
//增加
void attach(IObserver* observer) override;
void detach(IObserver* observer) override;
//通知
void notify() override;
//前台状态
string getAction() override;
void setAction(const string& _action) override;
private:
//同事列表
list<IObserver* > m_observers;
//前台状态
string m_sAction;
};
3.5.1 Secretary.cpp
#include "Secretary.h"
Secretary::Secretary()
{
}
void Secretary::attach(IObserver* observer)
{
m_observers.push_back(observer);
}
void Secretary::detach(IObserver* observer)
{
m_observers.remove(observer);
delete observer;
observer = nullptr;
}
void Secretary::notify()
{
for each (IObserver* observer in m_observers)
{
observer->update();
}
}
std::string Secretary::getAction()
{
return m_sAction;
}
void Secretary::setAction(const string& _action)
{
m_sAction = _action;
}
3.6.1 Boss .h
#pragma once
#include "ISubject.h"
#include <list>
class Boss :
public ISubject
{
public:
Boss();
virtual void attach(IObserver* observer) override;
virtual void detach(IObserver* observer) override;
virtual void notify() override;
virtual string getAction() override;
virtual void setAction(const string& action) override;
private:
list<IObserver* > m_observers;
string m_action;
};
3.6.2 Boss .cpp
#include "Boss.h"
Boss::Boss()
{
}
void Boss::attach(IObserver* observer)
{
m_observers.push_back(observer);
}
void Boss::detach(IObserver* observer)
{
m_observers.remove(observer);
}
void Boss::notify()
{
for each (IObserver* observer in m_observers)
{
observer->update();
}
}
std::string Boss::getAction()
{
return m_action;
}
void Boss::setAction(const string& action)
{
m_action = action;
}
3.7 main.cpp
#include<iostream>
#include "Secretary.h"
#include "StockObserver.h"
#include "NBAObserver.h"
#include "Boss.h"
void test3()
{
cout << "==============test3()=================" << endl;
Boss* pBoss = new Boss();
StockObserver* pObserver1 = new StockObserver("小白", pBoss);
NBAObserver* pObserver2 = new NBAObserver("小黄", pBoss);
pBoss->attach(pObserver1);
pBoss->attach(pObserver2);
pBoss->setAction("May I come in ?");
pBoss->notify();
//析构指针对象
delete pBoss;
pBoss = nullptr;
delete pObserver1;
pObserver1 = nullptr;
delete pObserver2;
pObserver2 = nullptr;
}
//实现了 具体观察者与具体通知者的 解耦
//之后可以随便扩展 通知者,随便扩展观察者,且每个通知者都可以与私下里与任意观察者交易,绑定与解绑,由每个通知者自己意愿决定
int main()
{
test3();
system("pause");
return 0;
}
此为《大话设计模式》学习心得系列 P123~~