观察者模式

1.动机

(1)在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。
(2)使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。

2.模式定义

定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
                                                            ——《设计模式》GoF

3.结构(Structure)

4.要点总结

(1)使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。
(2)目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。
(3)观察者自己决定是否需要订阅通知,目标对象对此一无所知。
(4)Observer模式是基于事件的UI框架中非常常用的设计模式,也是
MVC模式的一个重要组成部分。

5.示例

(1)未使用观察者模式

MainForm.cpp
class MainForm : public Form
{
	TextBox* txtFilePath;
	TextBox* txtFileNumber;
	ProgressBar* progressBar;

public:
	void Button1_Click(){

		string filePath = txtFilePath->getText();
		int number = atoi(txtFileNumber->getText().c_str());

		FileSplitter splitter(filePath, number, progressBar);

		splitter.split();

	}
};

FileSpiliter.cpp
class FileSplitter
{
	string m_filePath;
	int m_fileNumber;
	ProgressBar* m_progressBar;

public:
	FileSplitter(const string& filePath, int fileNumber, ProgressBar* progressBar) :
		m_filePath(filePath), 
		m_fileNumber(fileNumber),
		m_progressBar(progressBar){

	}

	void split(){

		//1.读取大文件

		//2.分批次向小文件中写入
		for (int i = 0; i < m_fileNumber; i++){
			//...
			float progressValue = m_fileNumber;
			progressValue = (i + 1) / progressValue;
			m_progressBar->setValue(progressValue);
		}

	}
};


(2)使用观察者模式

将控件类,和变化类分离。

IProgress相当于Observer类,MainForm,ConsoleNotify相当于ConcreteObserver。

FileSplitter相当于ConcreteSubject。

MainForm.cpp
class MainForm : public Form, public IProgress
{
	TextBox* txtFilePath;
	TextBox* txtFileNumber;

	ProgressBar* progressBar;

public:
	void Button1_Click(){

		string filePath = txtFilePath->getText();
		int number = atoi(txtFileNumber->getText().c_str());

		ConsoleNotifier cn;

		FileSplitter splitter(filePath, number);

		splitter.addIProgress(this); //订阅通知
		splitter.addIProgress(&cn); //订阅通知

		splitter.split();

		splitter.removeIProgress(this);

	}

	virtual void DoProgress(float value){
		progressBar->setValue(value);
	}
};

class ConsoleNotifier : public IProgress {
public:
	virtual void DoProgress(float value){
		cout << ".";
	}
};

FileSpliter.cpp
class IProgress{
public:
	virtual void DoProgress(float value)=0;
	virtual ~IProgress(){}
};


class FileSplitter
{
	string m_filePath;
	int m_fileNumber;

	List<IProgress*>  m_iprogressList; // 抽象通知机制,支持多个观察者
	
public:
	FileSplitter(const string& filePath, int fileNumber) :
		m_filePath(filePath), 
		m_fileNumber(fileNumber){

	}


	void split(){

		//1.读取大文件

		//2.分批次向小文件中写入
		for (int i = 0; i < m_fileNumber; i++){
			//...

			float progressValue = m_fileNumber;
			progressValue = (i + 1) / progressValue;
			onProgress(progressValue);//发送通知
		}

	}


	void addIProgress(IProgress* iprogress){
		m_iprogressList.push_back(iprogress);
	}

	void removeIProgress(IProgress* iprogress){
		m_iprogressList.remove(iprogress);
	}


protected:
	virtual void onProgress(float value){
		
		List<IProgress*>::iterator itor=m_iprogressList.begin();

		while (itor != m_iprogressList.end() )
			(*itor)->DoProgress(value); //更新进度条
			itor++;
		}
	}
};

#include <algorithm>
#include <vector>
#include <stdio.h>
#include "../Mutex.h"
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>

class Observable;

class Observer : public boost::enable_shared_from_this<Observer>
{
 public:
  virtual ~Observer();
  virtual void update() = 0;

  void observe(Observable* s);

 protected:
  Observable* subject_;
};

class Observable
{
 public:
  void register_(boost::weak_ptr<Observer> x);
  // void unregister(boost::weak_ptr<Observer> x);

  void notifyObservers()
  {
    muduo::MutexLockGuard lock(mutex_);
    Iterator it = observers_.begin();
    while (it != observers_.end())
    {
      boost::shared_ptr<Observer> obj(it->lock());
      if (obj)
      {
        obj->update();
        ++it;
      }
      else
      {
        printf("notifyObservers() erase\n");
        it = observers_.erase(it);
      }
    }
  }

 private:
  mutable muduo::MutexLock mutex_;
  std::vector<boost::weak_ptr<Observer> > observers_;
  typedef std::vector<boost::weak_ptr<Observer> >::iterator Iterator;
};

Observer::~Observer()
{
  // subject_->unregister(this);
}

void Observer::observe(Observable* s)
{
  s->register_(shared_from_this());
  subject_ = s;
}

void Observable::register_(boost::weak_ptr<Observer> x)
{
  observers_.push_back(x);
}

//void Observable::unregister(boost::weak_ptr<Observer> x)
//{
//  Iterator it = std::find(observers_.begin(), observers_.end(), x);
//  observers_.erase(it);
//}

// ---------------------

class Foo : public Observer
{
  virtual void update()
  {
    printf("Foo::update() %p\n", this);
  }
};

int main()
{
  Observable subject;
  {
    boost::shared_ptr<Foo> p(new Foo);
    p->observe(&subject);
    subject.notifyObservers();
  }
  subject.notifyObservers();
}
#include <algorithm>
#include <vector>
#include <stdio.h>

class Observable;

class Observer
{
 public:
  virtual ~Observer();
  virtual void update() = 0;

  void observe(Observable* s);

 protected:
  Observable* subject_;
};

class Observable
{
 public:
  void register_(Observer* x);
  void unregister(Observer* x);

  void notifyObservers()
  {
    for (size_t i = 0; i < observers_.size(); ++i)
    {
      Observer* x = observers_[i];
      if (x) {
        x->update(); // (3)
      }
    }
  }

 private:
  std::vector<Observer*> observers_;
};

Observer::~Observer()
{
  subject_->unregister(this);
}

void Observer::observe(Observable* s)
{
  s->register_(this);
  subject_ = s;
}

void Observable::register_(Observer* x)
{
  observers_.push_back(x);
}

void Observable::unregister(Observer* x)
{
  std::vector<Observer*>::iterator it = std::find(observers_.begin(), observers_.end(), x);
  if (it != observers_.end())
  {
    std::swap(*it, observers_.back());
    observers_.pop_back();
  }
}

// ---------------------

class Foo : public Observer
{
  virtual void update()
  {
    printf("Foo::update() %p\n", this);
  }
};

int main()
{
  Foo* p = new Foo;
  Observable subject;
  p->observe(&subject);
  subject.notifyObservers();
  delete p;
  subject.notifyObservers();
}

ObservableSubject是主题,里面有两种event进行订阅主题,Observer的函数onSubjectModified,和modified分别订阅了主题

#include <cstddef>
import <map>;
import <functional>;
import <iostream>;

using namespace std;

using EventHandle = size_t;

template <typename... Args>
class Event
{
public:
	virtual ~Event() = default; // Always a virtual destructor!

	// Adds an observer. Returns an EventHandle to unregister the observer.
	[[nodiscard]] EventHandle operator+=(function<void(Args...)> observer)
	{
		auto number{ ++m_counter };
		m_observers[number] = observer;
		return number;
	}

	// Unregisters the observer pointed to by the given handle.
	Event& operator-=(EventHandle handle)
	{
		m_observers.erase(handle);
		return *this;
	}

	// Raise event: notifies all registered observers.
	void raise(Args... args)
	{
		for (auto& observer : m_observers) {
			(observer.second)(args...);
		}
	}

private:
	size_t m_counter{ 0 };
	map<EventHandle, function<void(Args...)>> m_observers;
};


class ObservableSubject
{
public:
	auto& getEventDataModified() { return m_eventDataModified; }
	auto& getEventDataDeleted() { return m_eventDataDeleted; }

	void modifyData()
	{
		// ...
		getEventDataModified().raise(1, 2.3);
	}

	void deleteData()
	{
		// ...
		getEventDataDeleted().raise();
	}

public:
	Event<int, double> m_eventDataModified;
	Event<> m_eventDataDeleted;
};

void modified(int, double)
{
	cout << "modified" << endl;
}

class Observer
{
public:
	Observer(ObservableSubject& subject) : m_subject{ subject }
	{
		m_subjectModifiedHandle = m_subject.getEventDataModified() +=
			[this](int i, double d) { onSubjectModified(i, d); };
	}

	virtual ~Observer()
	{
		m_subject.getEventDataModified() -= m_subjectModifiedHandle;
	}

private:
	void onSubjectModified(int, double)
	{
		cout << "Observer::onSubjectModified()" << endl;
	}

	ObservableSubject& m_subject;
	EventHandle m_subjectModifiedHandle;
};

int main()
{
	ObservableSubject subject;

	auto handleModified{ subject.getEventDataModified() += modified };
	auto handleDeleted{ subject.getEventDataDeleted() += [] { cout << "deleted" << endl; } };
	Observer observer{ subject };

	subject.modifyData();
	subject.deleteData();

	cout << endl;

	subject.getEventDataModified() -= handleModified;
	subject.modifyData();
	subject.deleteData();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值