Contenitore / modello oggetto senza 'amico'

0

Ho una classe Container contenente oggetti di tipo Item . Sono classi diverse e in particolare non hanno una classe base comune (ad esempio, una Container non ha una Container ).:

class Container
{
    public ICollection<Item> Items { get { /* ... */ } }
}

class Item
{
    public Container Container { get { /* ... */ } }
}

Mi piacerebbe far rispettare che ogni Item deve avere esattamente un Container , e mi piacerebbe assicurarmi che non ci possa mai essere una situazione incoerente tale che, ad es. i.Container.Items.Contains(i) restituisce false.

Questo potrebbe essere fatto ad es. aggiungendo un metodo Container.AddItem che imposta di conseguenza la proprietà Item Container o un metodo Item.SetContainer che si presta a Container.Items .

Esempio:

class Item
{
    private Container container;
    public Container Container
    {
       get
       {
          return container;
       }
       set
       {
           if (container != null)
               container.Items.Remove(this);
           container = value;
           if (value != null)
               value.Items.Add(this);
       }
    }
}

Questo potrebbe essere fatto facilmente con il concetto di "amico", ma sto usando C # che non ha amici, e quindi questo codice di esempio non verrà compilato. Tuttavia, ovviamente sarebbe compilato se Container.Items avesse un setter pubblico, ma questo di nuovo consentirebbe incongruenze: un "utente" delle classi avrebbe bisogno di sapere di non usare il settatore di Container.Items , ma Item.Container invece.

Dopo aver cercato per un po 'di tempo, sento che non c'è modo di far rispettare questa restrizione che sembra essere così banale. (L'utilizzo di internal potrebbe essere una soluzione, ma nessuna soluzione.)

C'è un modo elegante per applicare questa regola di un contenitore per oggetto senza il concetto di "amico"?

    
posta Martin 04.04.2014 - 11:08
fonte

2 risposte

3

Potresti estrarlo in un servizio separato che ha l'unica resposnsibility per tenere traccia delle associazioni di Container < - > Item. Penso che questa sia una soluzione molto flessibile.

class Container<T>
{
    private IItemAssociations associations;
    public Container(IItemAssociations a)
    {
        this.associations = a;
    }

    public void Add(T i)
    {
        if (!associations.IsAddedToAContainer(i))
        {
            DoAdd(i);
            associations.AddAssociation(this, i);
        }
        else
            HandleAlreadyAdded(i);
    }
}

È possibile avere un metodo di costruzione statico che inietta un oggetto di associazione globale o utilizza un altro meccanismo di iniezione.

    
risposta data 04.04.2014 - 14:23
fonte
1

internal sarebbe una buona soluzione perché i container e gli oggetti sono inestricabilmente collegati, faranno parte dello stesso assembly.

Detto questo, questo è un odore di codice.

Gli oggetti in genere non dovrebbero sapere se appartengono a un contenitore, figuriamoci essere limitati a un solo contenitore. Questo è un incubo di accoppiamento poiché gli oggetti torneranno quindi inevitabilmente nel loro contenitore per cercare altri oggetti, stringendo quella relazione. Poi si entra in "come faccio a informare questo articolo che il pari di cui si è occupato ha improvvisamente lasciato il contenitore?" Il che rende quindi il contenitore interessato a quali articoli si preoccupano di quali altri articoli e in basso.

    
risposta data 04.04.2014 - 13:36
fonte

Leggi altre domande sui tag