一、UML圖
關鍵詞:Subject維護一個Observer列表,Subject執行Notify()時就執行列表中的每個Observer的Update()。
二、概念
觀察者模式:定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一主題對象。這個主題對象在狀態發生變化時,會通知所有觀察者對象,使他們能夠自動更新自己。
三、說明
角色:
(1)Subject類:可以翻譯爲主題或者抽象通知者,一般用一個抽象類或者一個接口實現。他把所有對觀察者對象的引用保存在一個聚集裏,每個主題都可以有任何數量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者對象。
(2)Observer類:抽象觀察者,爲所有的具體觀察者定義一個接口,在得到主題的通知時更新自己。這個接口叫做更新接口。抽象觀察者一般用一個抽象類或者一個接口實現。更新接口通常包含一個Update()方法,這個方法叫做更新方法。
(3)ConcreteSubject類:叫做具體主題或者具體通知者,將有關狀態存入具體觀察者對象;在具體主題的內部狀態改變時,給所有登記過的觀察者發出通知。
(4)ConcreteObserver類:具體觀察者,實現抽象觀察者角色所要求的更新接口,以便使本身的狀態與主題的狀態相協調。具體觀察者角色可以保存一個指向具體主題對象的引用。
什麼時候用觀察者模式?
(1)當一個對象的改變需要同時改變其他對象的時候;
(2)而且不知道具體有多少對象有待改變時,應該考慮使用觀察者模式;
(3)當一個抽象模型有兩個方面,其中一方面依賴於另一方面,這時用觀察者模式可以將這兩者封裝在獨立的對象中使他們各自獨立地改變和複用。
本質:
觀察者模式所做的工作其實就是在解除耦合,讓耦合的雙方都依賴於抽象,而不是依賴於具體。從而使得各自的變化都不會影響另一邊的變化。
四、C++實現
(1)Subject.h
#ifndef SUBJECT_H
#define SUBJECT_H
#include <string>
#include <list>
class Observer;
//Subject,抽象通知者或者主題
class Subject
{
protected:
std::string SubjectState;
public:
virtual void Attach(Observer* observer)=0;
virtual void Detach(Observer* observer)=0;
virtual void Notify()=0;
std::string GetSubjectState();
void SetSubjectState(std::string state);
};
//ConcreteSubject,具體通知者或者具體主題。
class Boss:public Subject
{
private:
std::list<Observer*> observers;
std::string action;
public:
void Attach(Observer* observer);
void Detach(Observer* observer);
void Notify();
};
#endif
(2)Subject.cpp
#include "Subject.h"
#include "Observer.h"
std::string Subject::GetSubjectState()
{
return SubjectState;
}
void Subject::SetSubjectState(std::string state)
{
this->SubjectState=state;
}
void Boss::Attach(Observer* observer)
{
observers.push_back(observer);
}
void Boss::Detach(Observer* observer)
{
std::list<Observer*>::iterator it;
for(it=observers.begin();it!=observers.end();it++)
{
if(*it==observer)
{
observers.erase(it);
break;
}
}
}
void Boss::Notify()
{
std::list<Observer*>::iterator it;
for(it=observers.begin();it!=observers.end();it++)
{
(**it).Update();
}
}
(3)Observer.h
#ifndef OBSERVER_H
#define OBSERVER_H
#include <list>
#include <iostream>
#include <string>
#include "Subject.h"
//Observer,抽象觀察者
class Observer
{
protected:
std::string name;
Subject* sub;
public:
Observer();
Observer(std::string name,Subject* sub);
virtual void Update();
bool operator==(const Observer&)const;
};
//ConcreteObserver,具體觀察者,股票觀察者
class StockObserver:public Observer
{
public:
StockObserver();
StockObserver(std::string name,Subject* sub);
void Update();
};
//ConcreteObserver,具體觀察者,NBA觀察者
class NBAObserver:public Observer
{
public:
NBAObserver();
NBAObserver(std::string name,Subject* sub);
void Update();
};
#endif
(4)Observer.cpp
#include "Observer.h"
Observer::Observer(){}
Observer::Observer(std::string name,Subject* sub)
{
this->name=name;
this->sub=sub;
}
void Observer::Update()
{
std::cout<<"Observer.Update()"<<std::endl;
}
bool Observer::operator==(const Observer& observer)const
{
return (this->name==observer.name)&&(this->sub==observer.sub);
}
StockObserver::StockObserver(){}
StockObserver::StockObserver(std::string name,Subject* sub)
{
this->name=name;
this->sub=sub;
}
void StockObserver::Update()
{
std::cout<<sub->GetSubjectState()<<" "<<name<<" "<<"關閉股市行情,繼續工作!"<<std::endl;
}
NBAObserver::NBAObserver(){}
NBAObserver::NBAObserver(std::string name,Subject* sub)
{
this->name=name;
this->sub=sub;
}
void NBAObserver::Update()
{
std::cout<<sub->GetSubjectState()<<" "<<name<<" "<<"關閉NBA直播,繼續工作!"<<std::endl;
}
(5)Client.cpp
#include "Observer.h"
#include <iostream>
#include <cstdlib>
//Client,客戶端
void main()
{
//通知者
Subject* huhansan=new Boss();
//4個觀察者實例
Observer* tongshi1=new StockObserver("魏關奼",huhansan);
Observer* tongshi2=new StockObserver("易管察",huhansan);
Observer* tongshi3=new NBAObserver("霍華德",huhansan);
Observer* tongshi4=new NBAObserver("林書豪",huhansan);
//將4個觀察者都加入到通知者的通知隊列中
huhansan->Attach(tongshi1);
huhansan->Attach(tongshi2);
huhansan->Attach(tongshi3);
huhansan->Attach(tongshi4);
//魏關奼沒有被老闆通知到,減去。
huhansan->Detach(tongshi1);
huhansan->SetSubjectState("我胡漢三回來了!");
//通知
huhansan->Notify();
delete huhansan;
delete tongshi1;
delete tongshi2;
delete tongshi3;
delete tongshi4;
std::cout<<""<<std::endl;
system("pause");
}
(6)運行截圖