Usa decoratore e fabbrica insieme per estendere gli oggetti?

2

Sono nuovo di OOP e modello di progettazione.

Ho una semplice app che gestisce la generazione di tabelle, colonne (che appartengono alla tabella), righe (che appartengono alla tabella e hanno colonne) e valori (che appartengono alle righe). Ciascuno di questi oggetti può avere una collezione di proprietà, che a sua volta è definita come enum.

Sono tutte interfacce: ho usato le fabbriche per ottenere esempi concreti di questi prodotti, a seconda delle circostanze.

Ora sto affrontando il problema di estendere queste classi. Diciamo che ho bisogno di un altro prodotto chiamato "SpecialTable" che a sua volta ha alcune proprietà speciali o nuovi metodi come "getSomethingSpecial" o un set esteso di proprietà. L'unico modo è estendere / specializzare tutti i miei elementi (ad esempio, costruire una SpecialTableFactory, un'interfaccia SpecialTable e un calcestruzzo SpecialTableImpl)? Che cosa fare se, diciamo, ho intenzione di utilizzare metodi standard come addRow (colonna colonna, nome stringa) che non ha bisogno di essere specializzato?

Non mi piace l'idea di ereditare fabbriche e interfacce, ma dal momento che SpecialTable ha più metodi di Table, credo che non possa condividere la stessa fabbrica. Mi sbaglio?

Un'altra domanda: se devo definire le proprietà del prodotto in fase di esecuzione (una tabella che è stata aggiornata a SpecialTable in fase di runtime), credo che dovrei usare un decoratore. È possibile (e in che modo) combinare la progettazione di fabbrica e decoratore? È preferibile utilizzare un modello di stato o di strategia, invece?

    
posta Gabriele B 25.11.2012 - 15:57
fonte

1 risposta

0

Sì, SpecialTable può essere prodotto dallo stesso factory (e dallo stesso metodo di fabbrica) che produce Table . Questo non è un problema, fintanto che SpecialTable fornisce almeno i metodi garantiti dall'interfaccia Table (che fa).

Questo tipo di situazione ha senso quando gli oggetti restituiti dalla fabbrica hanno un certo comportamento / funzionalità garantita (interfaccia Table ), e alcuni elementi facoltativi (interfaccia SpecialTable ).

Quindi, per utilizzare le abilità / elementi extra opzionali disponibili su alcuni oggetti concreti restituiti dalla fabbrica, hai alcune scelte:

  • usa il polimorfismo ( raccomandato )

  • utilizza instanceof (o simile), che può essere utilizzato per verificare la conformità dell'interfaccia / la digitazione esatta ( evita questo se possibile! )

Uso del polimorfismo

Un esempio per illustrare: supponiamo che SpecialTable abbia dati extra e un "widget" extra di widget che appare sull'interfaccia utente che rappresenta tabelle speciali. Hai davvero bisogno del codice che utilizza SpecialTable per sapere che è necessario aggiungere "blarg" all'interfaccia utente? O puoi semplicemente chiedere al tuo codice esterno di chiedere la cosa di tipo Tabella per aggiungere i suoi componenti UI necessari a qualche contenitore UI? Quindi il codice chiamante non si cura di quale sia il tipo esatto - SpecialTable si occupa di esso, aggiungendo il "blarg" al contenitore stesso. Questo pattern può essere descritto come il pattern delegate (talvolta anche noto come strategia )

.

Uso di instanceof (controllo del tipo)

Esempio di instanceof uso:

// Table and SpecialTable are interfaces
Table table = TableFactory.instance().getDefaultTable();

if (table instanceof "SpecialTable") {
  SpecialTable specialTable = (SpecialTable)table;
  specialTable.specialMethod();
}

table.normalMethod();

Tieni presente che quando definisci l'interfaccia SpecialTable puoi dichiararla come estendente l'interfaccia Tabella e quindi solo elencare i metodi aggiuntivi.

La tua fabbrica produrrà oggetti concreti di entrambi i tipi. Pertanto potresti avere una classe concreta chiamata BoringTable che implementa Table e una classe concreta chiamata ExcitingTable che implementa SpecialTable .

Attenzione instanceof!

In genere è meglio evitare cose come "instanceof" (o in generale, ifs di qualsiasi tipo che dipendono dal tipo di oggetto). Dovresti invece preferire il polimorfismo. Con questo intendo avere più classi diverse, di un tipo comune, che racchiudono un comportamento diverso nel loro codice di implementazione.

Chiedi questo: la classe che usa qualcosa di tipo Table (che potrebbe anche essere di tipo SpecialTable ) deve preoccuparsi se si tratta di una tabella speciale o no? Non puoi nascondere questa distinzione in una sorta di implementazione della SpecialTable - fai qualcosa di diverso, qualcosa in più, che fa semplicemente il vecchio Table?

    
risposta data 27.11.2012 - 16:36
fonte