Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Паттерн “VIP слушатель”

Anna | 17.06.2014 | нет комментариев
Признаюсь Добросовестно, изложение этого паттерна мне не встречалось, соответственно его наименование я выдумал. Если у кого есть информация о положительном наименовании, буду дюже рад услышать. Паттерн не привязан к языку но в данной статье я буду применять C#.

Картинка для привлечения внимания:

Выходит предположим себе систему состоящую из обслуживания, тот, что предоставляет иным частям системы отслеживать комплект объектов. Это может быть сервис симуляции предоставляющий список симулируемых объектов либо всякий иной схожий.

Объекты порождаемые и уничтожаемые системой:

	public interface IObject
	{
	}

Сервис, предоставляющий доступ к объектам:

	public delegate void ServiceChangedHandle(IService sender, IObject item, bool injected);

	public interface IService
	{
		IEnumerable<IObject> Items { get; }

		event ServiceChangedHandle OnServiceChanged;
	}

Тем системам, которым нужно трудиться с объектами, подписываются на событие, Дабы отслеживать возникновение новых объектов и исчезновение нынешних.

Нормальный пример слушателя:

	public class Listener
	{
		public void Initialise()
		{
			foreach (var item in service.Items)
				RegisterItem(item);

			service.OnServiceChanged  = OnServiceChanged;
		}

		public void Shutdown()
		{
			service.OnServiceChanged -= OnServiceChanged;

			foreach (var item in service.Items)
				UnregisterItem(item);
		}

		private void OnServiceChanged(IService sender, IObject item, bool injected)
		{
			if (injected)
				RegisterItem(item);
			else
				UnregisterItem(item);
		}

		private void RegisterItem(IObject item)
		{
			...
		}

		private void UnregisterItem(IObject item)
		{
			...
		}

		private IService service;
	}

При активизации слушателя он обрабатывает все объекты которые теснее присутствуют в сервисе а позже этого подписывается на метаморфозы списка объектов. При заключении работы слушателя нужно произвести обратные действия.
При многопоточном программировании все усложняется, потому что между опросом и подпиской, список объектов может изменится. Сервис должен будет предоставить объект синхронизации а слушатель заблокирует метаморфоза списка между обходом списка и подпиской.

Сервис с помощью многопоточности:

	public interface IService
	{
		...

		// Объект для синхронизации
		object SyncRoot { get; }
	}

Слушатель с помощью многопоточного обслуживания (Внутренняя синхронизация опущенна):

	public class Listener
	{
		public void Initialise()
		{
			// Добавляем синхронизацию
			lock (service.SyncRoot)
			{
				foreach (var item in service.Items)
					RegisterItem(item);

				service.OnServiceChanged  = OnServiceChanged;
			}
		}

		public void Shutdown()
		{
			// Добавляем синхронизацию
			lock (service.SyncRoot)
			{
				service.OnServiceChanged -= OnServiceChanged;

				foreach (var item in service.Items)
					UnregisterItem(item);
			}
		}

		...
	}

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

Подписчик для многопоточного и однопоточного варианта обслуживания (Внутренняя синхронизация опущена):

	public class Listener
	{
		public void Initialise()
		{
			service.OnServiceChanged  = OnServiceChanged;
		}

		public void Shutdown()
		{
			service.OnServiceChanged -= OnServiceChanged;
		}

		...
	}

Реализации обслуживания для однопоточного варианта:

	public class Service : IService
	{
		...

		public event ServiceChangedHandle OnServiceChanged
		{
			add
			{
				// Эмулируем добавление объектов для подписчика
				foreach (var item in items)
					value(this, item, true);

				// Непосредственная подписка
				eventHandle  = value;
			}
			remove
			{
				// Непосредственная отписка
				eventHandle -= value;

				// Эмулируем исчезновение объектов
				foreach (var item in items)
					value(this, item, false);
			}
		}

		private ServiceChangedHandle eventHandle;
		private List<IObject> items = new List<IObject>();
	}

Как и у всякого паттерна у этого варианта слушателя есть свои плюсы, минусы и область использования.

Плюсы:

  • Подписчики упрощаются, довольно легкой подписки и отписки
  • Идентичный код как для многопоточного так и для однопоточного варианта

Минусы:

  • При применении необходимо знать эту специфика у обслуживания, Дабы объекты не обрабатывать два раза

Из минусов и плюсов дозволено выделить область использования паттерна:

    • Присутствие небольшого числа сервисов и большого числа подписчиков
    • Внутренний продукт компании либо сугубо индивидуальный, предоставлять наружу такое поведение небезопасно
    • Суровая дисциплина проектирования и разработки. Всякий разработчик должен знать о таком поведении и знать где определенно применяется данный паттерн
    Каждому спасибо за внимание!
Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB