Modo corretto per estendere un albero gerarchico

3

Ho attualmente il seguente albero da implementare in Java.

I miei problemi sono i seguenti:

  • Come posso risolvere il fatto che l'amministratore deve avere tutto il livello 4 logica da entrambi i rami dell'albero poiché non posso ereditare tutti i 5 di dette classi?
  • Come posso refactoring l'albero per riflettere il fatto che al di fuori del livello 4 e la classe anonima, il resto non dovrebbe essere istanziato dal momento che non posso avere più abstract estendersi fino al livello 4 a causa delle restrizioni di Java? (Posso impostare il loro costruttore a privato e sii fatto con questo ma quello si sente una sorta di trucco a buon mercato per evitare qualche difetto di progettazione nel mio albero).
posta Leon 16.06.2017 - 15:28
fonte

2 risposte

3

Il problema qui è che sei stato indotto in errore nell'esprimere questo tipo di relazioni con l'ereditarietà. Non hai fatto nulla di sbagliato, questo problema caratterizza i problemi con l'ereditarietà e perché generalmente non è favorevole alla composizione.

Favor composition to inheritance

Ci sono molti approcci a questo problema, ma quello che segue è il più semplice:

Per prima cosa, hai una classe User, a differenza della tua gerarchia, questo rappresenta un utente di sistema, e questo è tutto.

Ovviamente, questi sono layout veloci, sostituiscono le proprietà con getter, setter, ecc.

interface HasSessionId
{ 
    ID;
}

interface CanCheckPermission
{
    HasPermissionTo(permission); 
}

class AnnoUser implements CanCheckPermission, HasSessionId
{
    ID;
}


class RegisterUser implements CanCheckPermission, HasSessionId
{
     ID;  
     UserName;
     FirstName;
     LastName;
     Login; //Sometimes it is helpful to separate the login into a a different concept to make impersonation easier, ect, you may or may not need this in your system.
}

Successivamente, hai i ruoli di sistema. Questa è una cosa completamente diversa da un utente. Qualsiasi comportamento o proprietà comuni che possono avere sono in un'interfaccia. Le interfacce implementano solo funzionalità minime e non dovrebbero essere viste come una classe base senza implementazione. Esprimono solo qualcosa che il sistema può fare.

interface IsAUser
{
    User;
}

interface CanBuy
{
     Buy(product);
}

I nostri singoli roll di sistema ora possono implementare queste interfacce per esprimere le loro funzioni disponibili, e sono libere di fare le cose diversamente se vogliono, ma possono avere un comportamento comune che vogliamo sfruttare, che è dove entra in gioco l'utilità di acquisto.

class BuyingUtility
{
   //static stuff is generally bad, but this is the closest Java has to functions. Avoid static fields as much as possible
   static Buy(product, IsAUser) { /*buy logic*/ }
}

class Admin implements IsAUser, CanBuy, CanSell
{
     User;
     Buy(product)
     {
           BuyingUtility.Buy(product, this);
     }
}

class BuyerManager implements IsAUser, CanBuy
{
     User;
     Buy(product)
     {
           BuyingUtility.Buy(product, this);
     }
}
    
risposta data 16.06.2017 - 17:01
fonte
2

Il fatto di aver creato diverse classi con funzionalità a volte mutuamente esclusive (acquirente o venditore) ea volte cumulativo (amministratore) dimostra che (quando si lavora con Java) queste non possono essere tutte class es. Pertanto, devi trovare un modello diverso, un po 'più complesso per rappresentare queste diverse entità.

Una scelta popolare è quella di creare classi che mantengano solo le diverse funzionalità e compongano gli oggetti che rappresentano l'entità reale da queste. La ricerca di mix-in , decoratori , tratti o faccette ti indirizzerà verso la documentazione di vari modelli consolidati per questo scopo.

    
risposta data 16.06.2017 - 15:52
fonte