观察者模式可以说是相当相当重要的一个设计模式,很多设计框架都是基于这一个设计模式的。比如我们最最熟悉的MVC,MVP,MVVM。那么观察者模式到底要解决一个什么问题呢?
现在假如在我们的系统中有A,B两个大的模块。我们可以先做这样一个假定。A模块在系统中负责信息展示与输入。B模块负责数据处理与存取。当上层用户通过A向整个系统输入数据后,A可以直接与B进行交互,把数据直接设置给B模块。然后B模块对数据进行一番处理后,将数据存入数据库,并且同时需要在A模块对数据进行更新显示。在传统的做法中,因为A是作为主调方存在,所以我们在数据输入阶段,可以很简单的在A模块中直接调用B模块的接口。但是在数据更新显示部分,我们就只能让A不断的去查询B模块的实时状态了,并将获取到的信息显示出来。
显然这是一种相当消耗性能的做法,而且我们知道一个不间断的查询工作是会阻塞线程的其他函数执行的,于是我们又需要单独开辟一个线程出来单独处理这个事情。对于一些特殊场景我们特事特例的处理可以,但是如果一个大型系统中有相当多的场景都是这样的,那么这将完全无法满足需求。所以我们希望的是B能自己通知A数据处理好了,数据有更新来驱动A的显示更新。让这个逻辑的驱动方由A换成B。这就是观察者模式需要做的。同时我们把场景在扩张开来。当B中数据有变化时,它不只需要通知A对象,还要同时C,D,E等等好多对象。当这些对象是确定的时候,那么直接通知OK。如果对象数量和具体是什么对象需要被通知到时再编码中不确定的时候。我们就需要在B与被通知对象中间加入一个观察者的角色。这个观察者负责监视B,B有变化告诉观察者就结束了。同样的这样的观察者也可以有很多很多,他们观察不用的东西。他们也同样可以动态的加入和退出。至于有最后具体要通知哪些对象由观察者负责。这样就是一个比较完整的观察者模式了。
具体的Java代码实现如下:
interface Observer{
public void update();
}
abstract class Subject{
protected ArrayList<Observer> observerList = new ArrayList<Observer>();
public void addObserver(Observer observer) {
if (observer != null) {
observerList.add(observer);
}
}
public void removeObserver(Observer observer) {
if(observer !=null) {
observerList.remove(observer);
}
}
public abstract void myNotify();
}
class SubjectA extends Subject{
@Override
public void myNotify() {
for(Observer observer : observerList) {
observer.update();
}
}
}
class ObserverA implements Observer{
@Override
public void update() {
System.out.println("ObserverA updating");
}
}
class ObserverB implements Observer{
@Override
public void update() {
System.out.println("ObserverB updating");
}
}
class ObserverC implements Observer{
@Override
public void update() {
System.out.println("ObserverC updating");
}
}
主调逻辑:
public static void main(String[] args) {
SubjectA suba = new SubjectA();
Observer obsa = new ObserverA();
Observer obsb = new ObserverB();
Observer obsc = new ObserverC();
suba.addObserver(obsa);
suba.addObserver(obsb);
suba.addObserver(obsc);
suba.myNotify();
}
输出结果:
ObserverA updating
ObserverB updating
ObserverC updating
同样的我们可以用C++来实现一遍:
class Observer{
public:
virtual void update() =0;
virtual ~Observer(){}
};
class Subject{
public:
void addObserver(Observer *observer){
observerList->push_back(observer);
}
void removeObserver(Observer *observer){
observerList->remove(observer);
}
virtual void notify() = 0;
protected:
list<Observer*> *observerList = new list<Observer*>();
};
class SubjectA : public Subject{
public:
void notify(){
for(list<Observer*>::iterator iter = observerList->begin(); iter != observerList->end(); iter++){
(*iter)->update();
}
}
};
class ObserverA : public Observer{
void update(){
cout << "ObserverA updating \n";
}
};
class ObserverB : public Observer{
void update(){
cout << "ObserverB updating \n";
}
};
int main(int argc, const char * argv[]) {
Subject *sub = new SubjectA();
Observer *obsa = new ObserverA();
Observer *obsb = new ObserverB();
sub->addObserver(obsa);
sub->addObserver(obsb);
sub->notify();
sub->removeObserver(obsa);
sub->notify();
return 0;
}
输出结果:
ObserverA updating
ObserverB updating
ObserverB updating
然后我们想想在C语言中的情况,简单一点处理的话其实就是一个回调函数的问题。我们可以把它实现的更接近C++和Java实现。
typedef struct _Observer{
void (*update)(struct _Observer * observer);
}Observer;
typedef struct _Subject{
Observer *observers[30];
int count;
void (*notify)(struct _Subject *subject);
void (*addObserver)(struct _Subject *subject, Observer *observer);
void (*removeObserver)(struct _Subject *subject, Observer *observer);
}Subject;
static void notify(struct _Subject *subject){
if(subject == NULL){
return;
}
for(int i = 0; i< subject->count; i++){
Observer * obs = subject->observers[i];
if(obs){
obs->update(obs);
}
}
}
static void addObserver(struct _Subject *subject, Observer *observer){
if(subject == NULL || observer == NULL){
return;
}
subject->observers[subject->count] = observer;
subject->count++;
}
static void removeObserver(struct _Subject *subject, Observer *observer){
if(subject == NULL || observer == NULL){
return;
}
//remove observer
}
static void update(struct _Observer * observer){
if (observer == NULL){
return;
}
printf("observer updating\n");
}
Observer * newObserver(){
Observer *observer = (Observer *)malloc(sizeof(Observer));
memset(observer, 0, sizeof(Observer));
observer->update =update;
return observer;
}
Subject *newSubject(){
Subject *subject = (Subject *)malloc(sizeof(Subject));
memset(subject, 0, sizeof(Subject));
subject->count = 0;
subject->addObserver = addObserver;
subject->removeObserver = removeObserver;
subject->notify = notify;
return subject;
}
int main(int argc, char** argv){
Subject * sub = newSubject();
Observer *obs = newObserver();
sub->addObserver(sub, obs);
sub->notify(sub);
return 0;
}
好了。分别用Java,C++,C实现了观察者模式。如果我们想研究MVC等框架。那么观察者模式就是其基础。