Наблюдатель (шаблон проектирования)

Материал из Seo Wiki - Поисковая Оптимизация и Программирование

Перейти к: навигация, поиск

Наблюдатель, Observer — поведенческий шаблон проектирования. Также известен как «подчинённые» (Dependents), «издатель-подписчик» (Publisher-Subscriber).

Содержание

Назначение

Определяет зависимость типа «один ко многим» между объектами таким образом, что при изменении состояния одного объекта все зависящие от него оповещаются об этом событии.

Реализация

Файл:Observer.png

При реализации шаблона «наблюдатель» обычно используются следующие классы.

  • 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


Поведенческие шаблоны проектирования

Interpreter/Интерпретатор | Template Method/Шаблонный метод | Command/Команда | Chain of Responsibility/Цепочка обязанностей | Iterator/Итератор, Cursor | Mediator/Посредник | Memento/Хранитель, Token | Observer/Наблюдатель, Listener | State/Состояние | Strategy/Стратегия | Visitor/Посетитель | Event listener | Single-serving visitor | Hierarchical visitor |

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:观察者模式

Личные инструменты

Served in 0.269 secs.