Uso dei costruttori per le istanze "a strati"

1

Sto lavorando su una libreria che può rappresentare virtualmente strisce di LED. La mia classe principale, LEDStrip , è astratta e ha un paio di metodi astratti, come getLength() e setColor(int index, Color c) . Ciò consente a chiunque implementa la classe di concentrarsi su pochi semplici metodi e lasciare che la classe genitrice esegua tutto il processo (come applicare modelli o "unire" due strisce virtualmente).

La mia domanda è come sarebbe meglio creare questi oggetti "sintetici" LEDStrip. Ci sono alcuni modi in cui posso pensare, ma non sono sicuro di quale sia considerata la migliore pratica:

Metodo 1: Classe e costruttore separati

public class JoinedLEDStrip extends LEDStrip {

    private LEDStrip strip1;
    private LEDStrip strip2;

    public JoinedLEDStrip(LEDStrip s1, LEDStrip s2) {
        strip1 = s1;
        strip2 = s2;
    }

    @Override
    protected void setLED(int LEDNum, Color c) {
        //Select which LEDStrip to set using length of first and second strips and apply offset
    }

    @Override
    public int getNumLEDs() {
        return strip1.getNumLEDs() + strip2.getNumLEDs();
    }
}

Questo avrebbe semplicemente una classe separata che implementa i metodi astratti della classe LEDStrip. È piuttosto semplice, ma sembra che potrebbe essere un po 'prolisso da usare in pratica.

LEDStrip joined = new JoinedLEDStrip(firstStrip, secondStrip);

Metodo 2: Fabbrica "Istanza"

//LEDStrip.java
public final LEDStrip join(LEDStrip strip) {
    return new LEDStrip() {

        private LEDStrip strip1 = LEDStrip.this;
        private LEDStrip strip2 = strip;

        @Override
        protected void setLED(int LEDNum, Color c) {
            //Select which LEDStrip to set using length of first and second strips and apply offset
        }

        @Override
        public int getNumLEDs() {
            return strip1.getNumLEDs() + strip2.getNumLEDs();
        }


    };
}

Questo metodo sembra abbastanza semplice, anche se la classe LEDStrip potrebbe diventare un po 'affollata, specialmente se ci sono più di poche versioni sintetiche diverse. Inoltre, non sarà particolarmente chiaro a un utente della libreria come possono creare nuove trasformazioni.

LEDStrip joined = firstStrip.join(secondStrip);

Metodo 3: qualcos'altro?

Forse c'è un altro metodo a cui non ho pensato. Una fabbrica statica sembra non essere particolarmente utile, ma sono sicuro che Java ha altri metodi che potrebbero funzionare meglio.

Quale via è considerata la pratica più accettata?

    
posta Daniel M. 09.02.2017 - 20:05
fonte

1 risposta

2

I tuoi due esempi sono per lo più equivalenti per la maggior parte. L'architettura del tuo sistema sarà effettivamente la stessa con entrambe le opzioni. Sono ugualmente estensibili.

L'unica differenza è se il tipo concreto che implementa strisce LED unite fa parte o meno dell'API pubblica. In particolare, l'esposizione di un metodo LEDStrip#join(LEDStrip) non richiede l'utilizzo di un tipo anonimo. Potrebbe anche essere implementato come LEDStrip join (LEDStrip other) { return new JoinedLEDStrip(this, other); } .

Un motivo per avere un metodo di istanza LEDStrip#join(LEDStrip) invece di usare un metodo statico (o equivalentemente, un costruttore) è se diversi tipi di strisce di LED vengano uniti in modo diverso. Per esempio. l'unione di una striscia LED unita potrebbe essere in grado di utilizzare alcune ottimizzazioni. In tal caso, il metodo di join nella tua classe base non deve essere definitivo in modo che possa essere sovrascritto. Ciò consente agli utenti della tua libreria di creare nuove sottoclassi di LEDStrip.

Tuttavia non è possibile aggiungere nuove operazioni in questo modo, ad es. un nuovo metodo LEDStrip#blink() . Se creerei una sottoclasse che aggiunge questo metodo, le sottoclassi esistenti non prenderebbero questo metodo. Se il nuovo comportamento fosse lo stesso per tutte le strisce LED, sarebbe sufficiente un metodo statico. Se ciascuna sottoclasse si comportasse in modo diverso, l'utilizzo del pattern visitor lo rende possibile, ma è possibile solo se la gerarchia dei possibili tipi di LEDStrip non cambia. Questo modello è quindi in disaccordo con la sottoclasse senza restrizioni.

Durante la progettazione della tua API, devi riflettere attentamente su come verrà utilizzata e su come gli utenti vorrebbero estenderla e aggiungere punti di estensione appropriati. La scelta che hai presentato è per lo più sintattica, ma qui ci sono valide considerazioni sull'estensibilità.

Lettura consigliata: il modello composito .

    
risposta data 10.02.2017 - 14:31
fonte