Metodo preferito per accedere a una classe esterna di metodi attraverso la classe originale

0

Voglio spostare un gruppo di metodi simili in una classe esterna. La classe è inizializzata con l'istanza di classe originale. Da lì posso accedervi per proprietà (istanza persistente) o per metodo (nuova istanza ogni volta).

Quale approccio è favorevole? In un sistema reale avrò molte di queste classi in possesso di molti metodi. Mi piacerebbe sentire le tue opinioni e conoscenze.

Esempio:

Ho una classe, chiamiamola Zoo, e nella mia classe Zoo tengo Liste di animali.

(Questi animali non hanno proprietà o metodi comuni in cui un'interfaccia o un'eredità sarebbero applicabili, questo è puramente per dare un esempio.)

public class Zoo
{
    public List<Monkey> MonkeyList;
    public List<Lion> LionList;
    public List<Turtle> TurtleList;

    public Zoo()
    {
        MonkeyList = new List<Monkey>();
        LionList = new List<Lion>();
        TurtleList = new List<Turtle>();
    }
}

Ora voglio aggiungere animali al mio Zoo, quindi creo alcuni metodi Aggiungi.

Invece di metterli direttamente nella mia classe Zoo, li aggiungo a una classe separata e passo l'istanza di Zoo, in questo modo:

public class ZooAdd
{
    private Zoo _zoo;

    public ZooAdd(Zoo zoo) 
    {
        _zoo = zoo;
    }

    public void Monkey(Monkey monkey)
    {
        _zoo.MonkeyList.Add(monkey);
    }

    public void Lion(Lion lion)
    {
        _zoo.LionList.Add(lion);
    }

    public void Turtle(Turtle turtle)
    {
        _zoo.TurtleList.Add(turtle);
    }       
}

Ora ho bisogno di aggiungere gli animali, ma di fronte a due opzioni, incerto che è preferibile:

Opzione 1: creo una proprietà

public class Zoo
{
    public ZooAdd Add;

    public Zoo
    {
        Add = new ZooAdd(this);
    }
}

...

Zoo zoo = new Zoo();
Monkey monkey = new Monkey();

zoo.Add.Monkey(monkey);

Opzione 2: creo un metodo per restituire un'istanza (modello di fabbrica?)

public class Zoo
{
    public ZooAdd Add()
    {
        return new ZooAdd(this);
    }
}

...

Zoo zoo = new Zoo();
Monkey monkey = new Monkey();

zoo.Add().Monkey(monkey);

Entrambi gli approcci soddisfano i requisiti e hanno poca differenza nell'aspetto.

Credo che la seconda opzione potrebbe rivelarsi più utile per l'efficienza della memoria poiché l'oggetto creato attraverso il metodo è presumibilmente consumato dal GC dopo l'uso, ma non ho alcuna conoscenza concreta in merito a tale affermazione.

Per favore, prestami la tua saggezza.

Modifica

Tutti voi avete sollevato alcune giustificate preoccupazioni riguardo al mio approccio e sono d'accordo sul fatto che possa essere migliorato. Aggiornerò la struttura delle mie lezioni con i tuoi suggerimenti e l'assistenza in mente. Grazie a tutti per le vostre risposte.

    
posta Jack 26.10.2018 - 17:32
fonte

4 risposte

5

Posso chiederti perché stai cercando di farlo? È difficile darti una guida senza conoscere la motivazione. Ma in entrambe le opzioni stai creando un oggetto e poi buttandolo via. Entrambe le opzioni sono ... non ottimali.

Se la tua motivazione è separare il codice, ci sono classi parziali in alcune lingue. Puoi anche creare una classe base che fornisce tutti i metodi di aggiunta.

Alcuni consigli non richiesti però ... i metodi dovrebbero essere verbi, parole d'azione. La scimmia non è un verbo. Quale azione viene intrapresa quando chiamo Monkey? Se sei in una lingua che lo supporta, aggiungerei semplicemente Sovrapponi ai diversi tipi di animali. Altrimenti, AddAnimalXXX sarebbe un nome di metodo migliore in quanto descrive quale azione sta prendendo il metodo. Codice di autocertificazione FTW! Le proprietà non dovrebbero avere effetti collaterali, quindi Aggiungi è una proprietà errata nell'opzione 1.

    
risposta data 27.10.2018 - 00:50
fonte
2

Nel tuo esempio non c'è molta differenza, ma generalmente trovo l'opzione 2 difficile da utilizzare.

Diventa più ovvio quando l'oggetto ha proprietà. ad esempio

Zoo.Add().BannanasIncluded = 2

Non funziona, quindi sei costretto a renderlo immutabile

Zoo.Add(bannanasIncuded:2).Monkey()

Inoltre, come faccio a sapere di non creare il mio addizionatore?

var x = new ZooAdder(myZoo)

o mantieni un riferimento a uno dopo essere stato usato?

var x = Zoo.Add(bannanasIncuded:2)
x.Monkey()
x.bannanasIncuded = 3 //why cant I do this??!?
x.Monkey()

O semplicemente usi direttamente il campo?

Zoo.MonkeyList.Add(new Monkey())

Anche dal punto di vista delle prestazioni, la raccolta e la raccolta di milioni di oggetti sommatori non è eccezionale.

In secondo luogo , suppongo tu stia creando queste classi per aggiungere un'interfaccia fluente piuttosto che aggiungere funzionalità?

Anche se va bene e alcune persone li adorano, non è essenziale per la classe e sarebbe meglio renderlo una dll separata, se possibile.

Potresti invece renderlo un metodo di estensione. Quindi posso aggiungere scimmie senza attività di scimmia.

    
risposta data 27.10.2018 - 09:11
fonte
2

Se vai con l'aproach di ZooAdd, violerai il principio Open Close : aggiungendo nuovi classi di animali allo Zoo dovresti anche aggiungere nuovi metodi a ZooAdd. Non capisco perfettamente cosa stai cercando di raggiungere, ma IMO ZooAdd non è il modo migliore per risolvere il tuo problema. Se vai a quel punto, dovrai mantenere la classe addizionale e i suoi test, e l'unico guadagno sarebbe lo zucchero sintetico sotto forma di:

zoo.Add.Monkey(monkey)

che può essere visto come una violazione della Legge di Demeter e può darti altri problemi in futuro.

Durante l'assegnazione delle responsabilità nelle lingue oo è bene usare Information Expert come guida e durante la progettazione delle chiamate ai messaggi tra gli oggetti è bene ricordare di Law of Demeter .

Imo dovresti andare con il piano e semplice:

public class Zoo
{
    public List<Monkey> Monkeys;
    public List<Lion> Lions;
    public List<Turtle> Turtles;

    public Zoo()
    {
        Monkeys = new List<Monkey>();
        Lions = new List<Lion>();
        Turtles = new List<Turtle>();
    }
}

e quindi puoi:

Zoo zoo = new Zoo();
Monkey monkey = new Monkey();

zoo.Monkeys.Add(monkey);
    
risposta data 04.11.2018 - 19:33
fonte
1

Molte ripetizioni di codice mi inducono a pensare che potrebbe mancare un'astrazione.

Il mio pensiero iniziale è di avere:

  • Una Animal della classe base
  • Un singolo List<Animal> in Zoo
  • Un singolo metodo Add(Animal animal) in Zoo
  • eredita la Animal della classe base per Monkey , Lion e qualsiasi altro animale che potresti voler aggiungere in futuro.

In alternativa, qualcosa che ho fatto io stesso in passato è usare qualcosa come Text Template Transformation Toolkit (T4) per generare codice ripetitivo e mettere il codice non generato in una classe parziale. Generalmente lo uso solo quando la ripetizione è inevitabile.

    
risposta data 29.10.2018 - 07:58
fonte

Leggi altre domande sui tag