Il favore accade quando entrambi i candidati si qualificano. Il problema indicato nella domanda non riesce su questo account, perché ha solo un'opzione di composizione.
"Anche la composizione potrebbe usare la generalizzazione". Questa affermazione ha senso per noi? Altrimenti, non siamo ancora pronti ad afferrare la regola del "favore".
Perché stiamo favorendo la composizione è che la composizione offre più possibilità di estensione / flessibilità rispetto alla generalizzazione. Questa estensione / flessibilità si riferisce principalmente alla runtime / flessibilità dinamica (che si ottiene con la combinazione di interfacce e composizione).
Il vantaggio non è immediatamente visibile. Per vedere il vantaggio è necessario attendere la successiva richiesta di modifica imprevista. Quindi, nella maggior parte dei casi, quelli che si attengono alla generalizzazione falliscono rispetto a quelli che hanno abbracciato la composizione (tranne un caso ovvio menzionato in seguito). Quindi la regola. Da un punto di vista dell'apprendimento se è possibile implementare con successo un'iniezione di dipendenza, allora si dovrebbe sapere quale privilegiare e quando. La regola ti aiuta a prendere una decisione quando non sei sicuro di quale scegliere. Anche in questo caso dovresti essere in grado di vedere entrambe le opzioni in primo luogo per favorirne una.
Sommario: Composizione: l'accoppiamento viene ridotto semplicemente aggiungendo alcune cose più piccole che si inseriscono in qualcosa di più grande, e l'oggetto più grande richiama solo l'oggetto più piccolo indietro. Generazione: da un punto di vista dell'API di terze parti che definisce che un metodo può essere sovrascritto è un impegno più strong rispetto alla definizione di un metodo che può essere chiamato (sicuramente vincente per la generalizzazione). E non dimenticare mai che con la composizione usi anche la generalizzazione, da un'interfaccia invece che da una grande classe. Ma l'intero merito va alla composizione, purtroppo.