Design pattern per forzare il client di una classe a chiamare un metodo

1

Ho una grande classe con proprietà complesse. Vorrei introdurre un'implementazione predefinita, consentire all'utente di eseguire l'override di parte dell'implementazione predefinita e assicurarsi inoltre che l'utente chiami un metodo di sincronizzazione in modo che l'oggetto sia sempre in uno stato coerente.

public class Complex {
    public int Id { get; set; }
    public CustomComplex1 Custom1 { get; set; }
    public CustomComplex2 Custom2 { get; set; }

    public Complex()
    {
        Custom1 = new CustomComplex1() { Name = "Bla", Cost = 55, etc..} // provide default values
    }

    //this method must always be called!
    public void RegisterObject()
    {

    }     

}

Class potrebbe essere usata in questo modo:

  var a = new Complex(); // all default values set
  a.Custom1.Name = "newName"; // I'd like to use the default values, but just change something..
  a.RegisterObject(); // problem - client might forget to call this! 

Ho pensato di usare il modello di builder, ma poi dovrò fornire metodi per modificare ogni variazione del tipo di CustomComplex1 - troppo lavoro e amp; Manutenzione. D'altra parte, se espongo Custom1 come proprietà pubblica, sembra che io stia facendo esattamente l'opposto dell'intento del modello di builder. Quindi, qual è un buon modo per A. consentire all'utente di modificare qualsiasi proprietà del mio oggetto complesso e B.force per chiamare RegisterObject in fase di compilazione?

    
posta BornToCode 10.12.2017 - 18:11
fonte

2 risposte

7

È possibile utilizzare il modello di builder. La roba "WithX" non è lo scopo principale del builder ed è solo lo zucchero di sintassi per semplificare l'utilizzo.

Il tuo codice, usando builder, potrebbe essere molto simile a questo:

var build = new ComplexBuilder(); // all default values set
build.Custom1.Name = "newName";
Complex a = build.Build(); // register inside here

Questo è un modello di build valido e normale.

    
risposta data 10.12.2017 - 18:35
fonte
1

Se non si desidera utilizzare il modello di builder e si desidera avere fantasia, è possibile utilizzare il delegato che modifica le impostazioni. Ho visto qualcosa di simile nella configurazione di ASP.NET Core.

public class Complex {
    public int Id { get; set; }
    public CustomComplex1 Custom1 { get; set; }
    public CustomComplex2 Custom2 { get; set; }

    public Complex(Action<CustomComplex1, CustomComplex2> configure)
    {
        Custom1 = new CustomComplex1() { Name = "Bla", Cost = 55, etc..} // provide default values
        configure(Custom1, Custom2);
        RegisterObject();
    }

    private void RegisterObject()
    {

    }
}

Il chiamante può quindi passare il delegato che modifica gli oggetti Custom .

Se non ti piace farlo in un costruttore, crea un metodo Create statico, rendi il costruttore privato e chiama il delegato e RegisterObject da lì.

    
risposta data 10.12.2017 - 18:40
fonte