Roman Macháček : Singleton v prostředí ASP.NET

Vzor Singleton patří mezi základní návrhové vzory a řeší obecně známou problematiku globální viditelnosti proměnných, resp. globální viditelnosti instancí tříd v rámci aplikace. 

Na problém globální viditelnosti v aplikaci narážíme, pokud chceme například sdílet instance nějakých tříd, typicky technologických tříd (datová vrstva, kolekce chyb, identita uživatele apod.), mezi objekty business logiky aplikace. Problém sdílení můžeme řešit pomoci předávání sdílených objektů business objektům jako parametrů v rámci volání metod nebo v rámci vytváření objektů, tedy v konstruktoru business tříd. Vybrané nevýhody tohoto řešení:

  • není flexibilní (co když budu chtít později přidat další sdílené technologické objekty)
  • narušuje se čistota business tříd, které nyní musí mít řadu přídavných parametrů v konstruktorech nebo metodách
  • komplikovanější volání objektů ...

Výrazně lepší řešení spočívá v návrhu sdílených tříd dle vzoru Singleton. Vystačíme ale s klasickou implementací vzoru Singleton v prostředí ASP.NET ? 

Singleton v prostředí .NET

Smyslem vzoru Singleton je zabezpečit, aby třída měla pouze jednu instanci globálně viditelnou ze všech bodů programu. 

Nejprve si ukažme klasickou implementaci vzoru Singleton v jazyce C#:

    	public class Singleton
	{
		private static Singleton mInstance=null;
		private Singleton()
		{
		}
		public static Singleton Instance
		{
			get
			{
				if (mInstance==null)
					mInstance=new Singleton();
				return mInstance;
			}
		}
	}
	
	//Získání sdílené instance
	Singleton.Instance
	

Globální viditelnost instance a její sdílení je zajištěno pomoci uložení instance do statické položky. Zjednodušeně můžeme říci, že pokud použijeme nějakou třídu takto implementovanou na lokální stanici, bude globální viditelnost instance omezena pro daného uživatele na této stanici.

Při návrhu ASP.NET aplikací, resp. obecněji při takovém návrhu aplikací, kde využíváme nějaký aplikační server jako pracovní prostor pro práci více uživatelů, tato klasická podoba vzoru nevyhovuje. Důvodem je oblast viditelnosti proměnných. Máme zde totiž dvě varianty globální viditelnosti:

  • globální viditelnost na úrovni aplikace
  • globální viditelnost na úrovni uživatelské seance 

Výše uvedená podoba Singletonu nám způsobí, že instance bude sdílena na úrovni celé aplikace, tj. i mezi jednotlivými uživateli pracující s touto aplikací. To je ale asi ve většině případů zcela nežádoucí. 

Modifikovaný Singleton v prostředí ASP.NET

Pro modifikaci oblasti viditelnosti využijeme technologický objekt Session, který v ASP.NET mají vývojáři k dispozici a který reprezentuje viditelnost na úrovni uživatelské seance v rámci aplikace.

    	public class Singleton
	{
		private Singleton()
		{
		}
		public static Singleton Instance
		{
			get 
			{
				if (HttpContext.Current.Session["Singleton"]==null)
					HttpContext.Current.Session["Singleton"]=new Singleton();
				return (Singleton)HttpContext.Current.Session["Singleton"];
			}
		}
	}
	
	//Získání sdílené instance
	Singleton.Instance
	

V modifikovaném Singletonu nejprve získáváme kontext aktuálního uživatele WEB aplikace a následně objekt Session. Při prvním vytváření instance Singletonu uložíme tuto instanci do Session uživatele, při dalších načítáních sdílené instance získáváme tuto instanci z objektu Session. 

Volání sdílených objektů v prostředí ASP.NET

Nyní se ještě podívejme na způsob volání globálních objektů v prostředí ASP.NET z pohledu jejich klientů. Mějme tedy dva klienty, dvě business třídy, v jejichž metodách chceme zapsat nějakou zprávu do globálního objektu sdílejícího zprávy. 

První část příkladu ukazuje přímé využívání objektu Session, druhá část ukazuje čistější volání s využitím třídy navržené jako Singleton.   

     	// varianta přímá práce se Session	
	// klient 1	
	Message msg=(Message)Session["Message"];
	msg.Add("Chyba1");
	// klient 2	
	Message msg=(Message)Session["Message"];
	msg.Add("Chyba2");

      	// varianta Singleton
	// klient 1	
	Message.Instance.Add("Chyba1");
	// klient 2	
	Message.Instance.Add("Chyba2");
	

Na závěr ještě uvádím několik výhod použití Singletonu v ASP.NET oproti sdílení objektů v Session (popř. Application) a to z pohledu klienta a implementace:

  • odstínění klienta od mechanismu sdílení instancí
  • jednodušší volání
  • flexibilnější řešení

 

 

 

Ing. Roman Macháček, Ph.D

OKD, a. s., člen koncernu KARBON INVEST, a.s.
Automatizace řízení-VOJ
729 41 Ostrava - Moravská Ostrava, Gregorova 3


V případě jakýchkoliv připomínek napište prosím na adresu objects@objects.cz