Шаблон Наблюдатель (Observer): структура, пример реализации на языке C# с использованием событий (Events)
Наблюдатель (англ. Observer) — поведенческий шаблон проектирования. Также известен как «подчинённые» (Dependents), «издатель-подписчик» (Publisher-Subscriber). Создает механизм у класса, который позволяет получать экземпляру объекта этого класса оповещения от других объектов об изменении их состояния, тем самым наблюдая за ними
Шаблон «наблюдатель» применяется в тех случаях, когда система обладает следующими свойствами:
· существует, как минимум, один объект, рассылающий сообщения;
· имеется не менее одного получателя сообщений, причём их количество и состав могут изменяться во время работы приложения;
· нет надобности очень сильно связывать взаимодействующие объекты, что полезно для повторного использования.
Данный шаблон часто применяют в ситуациях, в которых отправителя сообщений не интересует, что делают получатели с предоставленной им информацией.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace Observer
{
/// <summary>
/// Observer Pattern Judith Bishop Jan 2007
/// Updated by Kobel' Bohdan 2013
///
/// 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;
}
}
interface ISubject
{
void AddObserver(IObserver observer);
void RemoveObserver(IObserver observer);
void NotifyObservers(string s);
}
class Subject : ISubject
{
public string SubjectState { get; set; }
public List<IObserver> Observers { get; private set; }
private Simulator simulator;
private const int speed = 200;
public Subject()
{
Observers = new List<IObserver>();
simulator = new Simulator();
}
public void AddObserver(IObserver observer)
{
Observers.Add(observer);
}
public void RemoveObserver(IObserver observer)
{
Observers.Remove(observer);
}
public void NotifyObservers(string s)
{
foreach (var observer in Observers)
{
observer.Update(s);
}
}
public void Go()
{
new Thread(new ThreadStart(Run)).Start( );
}
void Run ()
{
foreach (string s in simulator)
{
Console.WriteLine("Subject: " + s);
SubjectState = s;
NotifyObservers(s);
Thread.Sleep(speed); // milliseconds
}
}
}
interface IObserver
{
void Update(string state);
}
class Observer : IObserver
{
string name;
ISubject subject;
string state;
string gap;
public Observer(ISubject subject, string name, string gap)
{
this.subject = subject;
this.name = name;
this.gap = gap;
subject.AddObserver(this);
}
public void Update(string subjectState)
{
state = subjectState;
Console.WriteLine(gap + name + ": " + state);
}
}
}