Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шаблоны и архитектура программ.doc
Скачиваний:
12
Добавлен:
04.05.2019
Размер:
558.08 Кб
Скачать

Наблюдатель (Observer)

Шаблон Наблюдатель определяет отношение между объектами таким образом, что когда один из объектов меняет своё состояние, все другие объекты получают об этом уведомление.

Иллюстрацией применения шаблона Наблюдатель служит знакомая по языку C# система событий. Один объект публикует событие, остальные объекты могут подписаться на событие и получать уведомление о его наступлении. Собственно, основное назначение шаблона Наблюдатель – это реализация системы работы с событиями.

Как и в случае с шаблоном Посредник, дизайн шаблона Наблюдатель предполагает наличие двух выделенных классов. Объект класса Subject изменяет своё состояния, и именно эти изменения предполагается отслеживать. Объекты (их может быть несколько) класса Observer могут подписываться на отслеживание изменений. Класс Subject располагает закрытым событием с именем Notify. Как только Subject изменяет своё состояние, событие активируется. При этом вызывается метод Update() подписчиков, которому передаётся состояние объекта Subject. Метод Update() предварительно регистрируется в Subject при помощи операции Attach().

Рис. 22. Дизайн шаблона Наблюдатель.

Далее приводится пример кода, демонстрирующего реализацию шаблона Наблюдатель. Заметим, что в примере намеренно не используются события.

using System;

using System.Collections.Generic;

// аналог Subject

public abstract class Stock

{

private double price;

private readonly IList<IInvestor> investors =

new List<IInvestor>();

public double Price

{

get { return price; }

set

{

if (price != value)

{

price = value;

Notify();

}

}

}

public string Symbol { get; private set; }

protected Stock(string symbol, double price)

{

Symbol = symbol;

this.price = price;

}

public void Attach(IInvestor investor)

{

investors.Add(investor);

}

public void Detach(IInvestor investor)

{

investors.Remove(investor);

}

public void Notify()

{

foreach (var investor in investors)

{

investor.Update(this);

}

}

}

public class IBM : Stock

{

public IBM(double price) : base("IBM", price) { }

}

// интерфейс, аналогичный IObserver

public interface IInvestor

{

void Update(Stock stock);

}

// конкретный обозреватель

public class Investor : IInvestor

{

public string Name { get; private set; }

public Stock Stock { get; set; }

public Investor(string name)

{

Name = name;

}

public void Update(Stock stock)

{

Console.WriteLine("Notified {0} of {1}'s change to {2:C}",

Name, stock.Symbol, stock.Price);

}

}

public class ObserverExample

{

private static void Main()

{

var ibm = new IBM(120.00);

ibm.Attach(new Investor("Sorros"));

ibm.Attach(new Investor("Berkshire"));

ibm.Price = 120.10;

ibm.Price = 121.00;

ibm.Price = 120.50;

ibm.Price = 120.75;

Console.ReadKey();

}

}