Наблюдатель (шаблон проектирования)
Наблюдатель, Observer — поведенческий шаблон проектирования. Также известен как «подчинённые» (Dependents), «издатель-подписчик» (Publisher-Subscriber).
Назначение
Определяет зависимость типа «один ко многим» между объектами таким образом, что при изменении состояния одного объекта все зависящие от него оповещаются об этом событии.
Реализация
При реализации шаблона «наблюдатель» обычно используются следующие классы.
- Observable — интерфейс, определяющий методы для добавления, удаления и оповещения наблюдателей.
- Observer — интерфейс, с помощью которого наблюдаемый объект оповещает наблюдателей.
- ConcreteObservable — конкретный класс, который реализует интерфейс Observable.
- ConcreteObserver — конкретный класс, который реализует интерфейс Observer.
Область применения
Шаблон «наблюдатель» применяется в тех случаях, когда система обладает следующими свойствами:
- существует, как минимум, один объект, рассылающий сообщения
- имеется не менее одного получателя сообщений, причём их количество и состав могут изменяться во время работы приложения.
Данный шаблон часто применяют в ситуациях, в которых отправителя сообщений не интересует, что делают с предоставленной им информацией получатели.
Примеры
PHP5
interface Observer{
function notify($obj);
}
class ExchangeRate{
static private $instance = NULL;
private $observers = array();
private $exchange_rate;
private function ExchangeRate(){
}
static public function getInstance(){
if(self::$instance == NULL){
self::$instance = new ExchangeRate();
}
return self::$instance;
}
public function getExchangeRate(){
return $this->exchange_rate;
}
public function setExchangeRate($new_rate){
$this->exchange_rate = $new_rate;
$this->notifyObservers();
}
public function registerObserver($obj){
$this->observers[] = $obj;
}
function notifyObservers(){
foreach($this->observers as $obj){
$obj->notify($this);
}
}
}
class ProductItem implements Observer{
public function __construct(){
ExchangeRate::getInstance()->registerObserver($this);
}
public function notify($obj){
if($obj instanceof ExchangeRate) {
// Update exchange rate data
print "Received update!\n";
}
}
}
$product1 = new ProductItem();
$product2 = new ProductItem();
ExchangeRate::getInstance()->setExchangeRate(4.5);
Пример на C#
using System;
using System.Collections;
using System.Threading;
namespace Observer
{
/// <summary>
/// Observer Pattern Judith Bishop Jan 2007
///
/// The Subject runs in a thread and changes its state
/// independently. At each change, it notifies its Observers.
/// </summary>
class Program
{
static void Main(string[] args)
{
Subject subject = new Subject();
Observer Observer = new Observer(subject,"Center","\t\t");
Observer observer2 = new Observer(subject,"Right","\t\t\t\t");
subject.Go();
// Wait for user
Console.Read();
}
}
class Simulator : IEnumerable {
string [] moves = {"5","3","1","6","7"};
public IEnumerator GetEnumerator()
{
foreach( string element in moves )
yield return element;
}
}
class Subject {
public delegate void Callback (string s);
public event Callback Notify;
Simulator simulator = new Simulator( );
const int speed = 200;
public string SubjectState { get; set; }
public void Go()
{
new Thread(new ThreadStart(Run)).Start( );
}
void Run ()
{
foreach (string s in simulator)
{
Console.WriteLine("Subject: " + s);
SubjectState = s;
Notify(s);
Thread.Sleep(speed); // milliseconds
}
}
}
interface IObserver
{
void Update(string state);
}
class Observer : IObserver
{
string name;
Subject subject;
string state;
string gap;
public Observer(Subject subject, string name, string gap)
{
this.subject = subject;
this.name = name;
this.gap = gap;
subject.Notify += Update;
}
public void Update(string subjectState)
{
state = subjectState;
Console.WriteLine(gap + name + ": " + state);
}
}
}
C++
#include <iostream>
#include <string>
#include <map>
#include <boost/foreach.hpp>
class SupervisedString;
class IObserver{
public:
virtual void handleEvent(const SupervisedString&) = 0;
};
class SupervisedString{ // Observable class
std::string _str;
std::map<IObserver* const, IObserver* const> _observers;
typedef std::map<IObserver* const, IObserver* const>::value_type item;
void _Notify(){
BOOST_FOREACH(item iter, _observers){
iter.second->handleEvent(*this);
}
}
public:
void add(IObserver& ref){
_observers.insert(item(&ref, &ref));
}
void remove(IObserver& ref){
_observers.erase(&ref);
}
const std::string& get() const{
return _str;
}
void reset(std::string str){
_str = str;
_Notify();
}
};
class Reflector: public IObserver{ // Prints the observed string into std::cout
public:
virtual void handleEvent(const SupervisedString& ref){
std::cout<<ref.get()<<std::endl;
}
};
class Counter: public IObserver{ // Prints the length of observed string into std::cout
virtual void handleEvent(const SupervisedString& ref){
std::cout<<"length = "<<ref.get().length()<<std::endl;
}
};
int main(){
SupervisedString str;
Reflector refl;
Counter cnt;
str.add(refl);
str.reset("Hello, World!");
std::cout<<std::endl;
str.remove(refl);
str.add (cnt);
str.reset("World, Hello!");
std::cout<<std::endl;
return 0;
}
Примечания
См. также
Ссылки
реализация паттерна observer(наблюдатель) на javascript
bg:Наблюдател (шаблон) ca:Patró observador cs:Observer de:Observer (Entwurfsmuster) en:Observer pattern es:Observer (patrón de diseño) fr:Observateur (patron de conception) it:Observer pattern ja:Observer パターン ko:옵저버 패턴 nl:Observer pl:Obserwator (wzorzec projektowy) pt:Observer th:อ็อบเซิร์ฟเวอร์แพตเทิร์น zh:观察者模式
Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....