Inizializzazione di oggetti in Constructor

6

Ho sotto il costruttore, dove crea una cartella di lavoro nel costruttore. Ho letto che, idealmente, non dovremmo creare oggetti in Constructor, invece dovremmo avere solo dei compiti che vengono passati.

public ExcelWriter() {
        workbook = new HSSFWorkbook();
        //other code
    }

Va bene creare oggetti fissi come sopra? Qual è la soluzione alternativa ideale? e dal punto di vista del test unitario? Se passare la cartella di lavoro dal codice del metodo chiamante in un'altra classe, dobbiamo anche creare l'oggetto cartella di lavoro anche lì.

È più tardi un approccio migliore? Com'è meglio o importa rispetto all'approccio del costruttore?

    
posta dgr 25.01.2017 - 05:32
fonte

4 risposte

11

Per i programmatori principianti questo va bene.

Tuttavia, come hai detto tu, se vuoi testare questa classe ExcelWriter , potresti forse dare l'oggetto HSSFWorkbook come argomento nel costruttore piuttosto che crearlo tu stesso. In questo modo, puoi utilizzare quello reale nel tuo codice e utilizzare una simulazione nei test di unità. Questa pratica è chiamata iniezione di dipendenza .

Quindi il tuo costruttore sarebbe:

public ExcelWriter(HSSFWorkbook hssfWorkBook) {
    workbook = hssfWorkBook;
    // other code
}

Quindi, da qualche altra parte nel tuo codice, chiami quel costruttore:

HSSFWorkbook myWorkbook = new HSSFWorkbook();
ExcelWriter myExcelWriter = new ExcelWriter(myWorkbook);

E il tuo test unitario sarebbe qualcosa del tipo:

HSSFWorkbook myMockedWorkbook = // create a mock
ExcelWriter testWriter = new ExcelWriter(myMockedWorkbook);

Se vuoi farlo ancora meglio, usa le interfacce, così finirai con due classi separate:

public interface IWorkbook {}

public class RealWorkbook implements IWorkbook {
    // this is the one for in your code
}

public class FakeWorkbook implements IWorkbook {
    // this is the one you use in your unit test
}
    
risposta data 25.01.2017 - 08:47
fonte
5

Nulla nel mondo reale è l'ideale. Ma una soluzione alternativa è chiamata iniezione di dipendenza :

public class ExcelWriter {
    Workbook workbook;
    public ExcelWriter(Workbook workbook) {
        this.workbook = workbook;
    }
    //other code
}

public void main(){        
    Writer writer = new ExcelWriter( new HSSFWorkbook() );       

    //other code
}

In questo modo ExcelWriter può funzionare con qualsiasi tipo di Workbook .

    
risposta data 25.01.2017 - 10:01
fonte
1

Si riduce alla semantica.

Se l'istanziazione si trova nel contesto di un wrapper per migliorare la funzionalità di una cartella di lavoro (ereditarietà o composizione), l'istanziazione dell'oggetto all'interno del costruttore è soddisfacente. Dovresti applicare la regola "composizione sull'ereditarietà".

Se componi Oggetti per creare una nuova semantica disgiunta, dovresti chiederti se vuoi essere dipendente dalla classe concreta come devi sapere per istanziarla.

Se non si hanno problemi con la dipendenza concreta (che può violare il principio di inversione delle dipendenze) l'istanza dell'oggetto nel costruttore o l'inizializzazione pigra sono semanticamente identiche. L'inizializzazione pigra rimanda solo l'istanziazione fino a quando non è necessaria. Si astraggono dal momento in cui viene creato un oggetto.

Se potresti avere più versioni di una cartella di lavoro sotto un'astrazione, dovresti preferire passare l'oggetto nel costruttore sotto questa astrazione. Su un oggetto di alto livello, dovresti considerare la funzionalità del contenitore. Esistono diverse possibilità di tecnologie di iniezione delle dipendenze.

    
risposta data 03.02.2017 - 10:08
fonte
-2

Utilizza inizializzazione pigra . Crea la cartella di lavoro solo quando qualcuno ne ha bisogno, ad es. il metodo DoSomething in questo esempio:

public class ExcelWriter {
    Workbook workbook = null;
    public ExcelWriter() {
        //nop
    }

    protected Workbook getWorkbook() {
        if (workbook == null) workbook = new Workbook();
        return workbook;
    }

    public doSomething() {
        Workbook wb = getWorkbook();
    }
}
    
risposta data 25.01.2017 - 23:08
fonte

Leggi altre domande sui tag