Čím nahradit singleton? rubrika: Programování: Jiné

3 SebastianBusek
položil/-a 14.8.2014

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?

Komentáře

  • xxar3s : Odporucam prejst na Windsor oproti Unity je to ako Lambo vs. Fabia 17.8.2014
odkaz Vyřešeno
7 mkoubik
odpověděl/-a 14.8.2014

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:

Rychlé přihlášení přes sociální sítě:

Nebo se přihlaste jménem a heslem:

Zadejte prosím svou e-mailovou adresu.
Zadejte své heslo.