Perché un builder dovrebbe essere una classe interna anziché nel suo file di classe?


24

Molti Builder Patternesempi rendono la Builderclasse interna dell'oggetto che costruisce.

Questo ha un senso dal momento che indica quali sono le Builderbuild. Tuttavia, in un linguaggio tipicamente statico sappiamo quali sono le Builderbuild.

D'altra parte se si Buildertratta di una classe interna, dovresti sapere quale classe Buildercostruisce senza guardare all'interno di Builder.

Inoltre, avere il builder come classe interna riduce il numero di importazioni poiché può essere referenziato dalla classe esterna - se ti interessa.

E poi ci sono esempi pratici in cui il Builderè nello stesso pacchetto, ma non una classe interna, come StringBuilder. Sai che Builder dovrebbe creare un Stringperché è così chiamato.

Detto questo, l'unica buona ragione che mi viene in mente per creare una Builderclasse interiore è che sai qual è la classe Buildersenza conoscerne il nome o fare affidamento su convenzioni di denominazione. Ad esempio, se StringBuilderfosse stata una classe interiore Stringprobabilmente avrei saputo che esisteva prima di me (speculativo).

Ci sono altri motivi per creare Builderuna classe interiore o dipende solo dalle preferenze e dal rituale?

Risposte:


30

Penso che il motivo per farlo sia che la classe interna (il Costruttore) possa accedere ai membri privati ​​della classe che sta costruendo.

Da http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

Le classi nidificate non statiche (classi interne) hanno accesso ad altri membri della classe che la racchiude, anche se sono dichiarate private.

...

Considera due classi di livello superiore, A e B, in cui B ha bisogno di accedere ai membri di A che altrimenti verrebbero dichiarati privati. Nascondendo la classe B all'interno della classe A, i membri di A possono essere dichiarati privati ​​e B può accedervi.

...

Come per i metodi e le variabili di istanza, una classe interna è associata a un'istanza della sua classe chiusa e ha accesso diretto ai metodi e ai campi di quell'oggetto.

Ecco un po 'di codice per provare a illustrare questo:

class Example {

    private int x;

    public int getX() { return this.x; }

    public static class Builder {

        public Example Create() {
            Example instance = new Example();
            instance.x = 5; // Builder can access Example's private member variable
            return instance;
        }
    }
}

Come classe statica, Builder non ha un'istanza specifica di Esempio a cui è legata. Tuttavia, data un'istanza di Esempio (o quella che crea se stessa) Builder può ancora accedere ai membri privati ​​di quell'istanza.


Ottima risposta, ha senso! Tuttavia, i modelli di generatore di solito hanno una classe interna statica e potrebbero accedere solo ai membri privati ​​statici della classe esterna. Se avessi un costruttore per una classe istanziata, sarebbe strano.
Nathanial,

1
@Nathanial affatto, sono accessibili anche le variabili dell'istanza privata: ideone.com/7DyjDR
amon

1
@nathanial: Sì, ma il builder non sta manipolando la classe; sta manipolando un oggetto della classe che il costruttore stesso ha istanziato.
Robert Harvey,

@amon vedo cosa hai fatto lì. Grazie per la spiegazione!
Nathanial,

In particolare, dà al costruttore l'accesso a un costruttore privato per la classe che viene costruita, consentendo a quella classe di essere immutabile (tutti i campi finali) e solo istantanea tramite il costruttore.
Matthew McPeak,

1

Non c'è "dovrebbe" in questo caso. Definire un builder all'interno di un'altra classe o averlo separato è ortogonale al modello Builder. Molti esempi lo fanno per comodità di presentare il codice in un file coerente (anche per l'accesso ai membri privati, ma dipende anche dal contesto). Sentiti libero di fare diversamente


Non sono sicuro del motivo per cui questa risposta non è stata votata, per qualsiasi motivo diverso da "perché non è così che lo facciamo in Java". Il Builder Pattern fornisce un wrapper attorno a un costruttore che accetta un sacco di parametri. Se il costruttore accetta tali parametri, non è necessario che l'oggetto Builder acceda ai membri privati.
Greg Burghardt,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.