Čím nahradit singleton? rubrika: Programování: Jiné
Krásný den všem vývojářům,
mám v podstatě hrozně jednoduchou otázku - čím nahradit singleton?
Ale začnu mým use-case. Jde o to, že když vytvářím instanci třídy A, tak potřebuji aby manager si poznamenan, že instance třídy A byla vytvořena (vloží si ji do zásobníku (pořadí musí zůstat zachováno)). Současně s tím, mám požadavek, aby manager byl v aplikaci pouze jeden.
Takový klasický přístup je, že mám depencency injection container, kde určím, že pro instance managera bude použita právě jedna instance.
Problém je v tom, že když Unity (jde o C# a pro DIC používám Unity) resolvuje závislosti vytváří jejich instance a protože v době instancování třídy A nejsou dostupné ostatní instance (hlavně mám na mysli zmíněného managera) tak konstruktor padne na NullReferenceException.
Důvod proč potřebuji tuhle logiku vykonat v konstruktoru je ten, že pak mám třídu X, která také používá managera a žádá jej o vydání poslední instance A. Příklad použití:
using (A a = new A()) { // x je už instancované pomocí Unity a jde o třídu X var foo = x.SayHelloJohnDoe(); // x v metodě SayHelloJohnDoe() volá managera a žádá jej o poslední instanci A }
A právě tady používám singleton nad managerem, ale moc se mi to nelíbí a hledám způsob, tak jej nahradit. Napadá Vás něco?
Nevytvářej objekty té třídy ručně, ale vytvoř si na ně továrnu a tu si předávej kam potřebuješ.
class AFactory { public AFactory(AManager manager) { this.manager = manager; } public A create() { a = new A(); manager.register(a); return a; } }
Komentáře
- Augi : Jen dodám: nedělej nic v konstruktoru. — 14.8.2014
- Kit : Stačí ten konstruktor udělat private. — 14.8.2014
- SebastianBusek : @mkoubik: díky za odpověď. Jestli to chápu správně, tak navrhuješ nevolat using (A a = new A()) { // ... } ale použít // _afactory je/bude inicializována skrze Unity using (A a = _afactory.Create()) { // ... } Jen mám problém právě s tím voláním _afactory.Create(). Musím si asi ještě nechat projít hlavou, jestli chci/je možné aby existovala A bez managera. Protože pokud ne, tak by taková těsná vazba na managera mohla být relativně odpustitelná, nemyslíš? @Augi: souhlasím, konstruktor by měl obsahovat pouze inicializaci. @Kit: neptám se jak vytvořit Singleton, ale čím jej nahradit... :) Ale pokud to byla reakce na to co napsal mkoubik, tak Unity vyžaduje public konstruktor. — 15.8.2014
- Kit : Singletonu se úspěšně vyhýbám, zatím jsem pro něj nenašel uplatnění. Unity neznám. — 15.8.2014
- xxar3s : Kit: Singleton sa hodi ak chces pocas celeho zivotneho cyklu aplikacie pri resolvovani z kontaineru pre jeden typ dostat vzdy rovnaku instanciu. Velakrat je ale lepsie zvolit per request alebo per session life time. — 17.8.2014
- Kit : Kontejnery nepoužívám, takže mám o důvod méně. Místo kontejneru mám model, který tu instanci dostane a pak ji distribuuje dle potřeby. — 17.8.2014
- Honza Břešťan : Jsou pripady, kdy singleton dava smysl (ruzne connection/cluster pooly, event/message brokery, skoro vsechno v jadru her...). IoC kontejner jen umoznuje se konfiguracne rozhodnout, jestli chci v danem pripade singleton nebo jiny lifecycle. Plus tim, ze takova "singleton" trida je porad normalni trida a svuj lifecycle neresi (na rozdil od klasickeho singleton patternu), zjednodusuje pripadnou kompozici nebo subclassing. Ale samozrejme ne ze by to neslo i bez kontejneru proste tim, ze si nekde "nahore" budu drzet jednu instanci a predavat ji rucne. — 17.8.2014
- Kit : Dokud dělám poctivé DI bez kontejnerů, Singleton nepořebuji. — 18.8.2014
Pro plný přístup na Devel.cz se prosím přihlaste:
Nebo se přihlaste jménem a heslem:
Komentáře