Modifica del comportamento della classe astratta senza modificare sottoclassi

0

Sto affrontando un problema con il cambiamento del comportamento di una libreria (quindi non posso o non voglio cambiare i suoi interni a causa di futuri aggiornamenti, ecc.).

In questa libreria c'è una classe astratta che condivide pochi metodi con tutte le sue sottoclassi. Ora ho bisogno di cambiare alcuni metodi in questa super classe astratta senza cambiare le sottoclassi. Mi chiedevo quale schema dovrei applicare a questo senza riscrivere il tutto.

Uso PHP, quindi potrei usare un tratto per sovrascrivere questi metodi nelle mie sottoclassi secondarie che userò poi nel mio codice cliente. Ciò comporterebbe la creazione delle sottoclassi secondarie e l'aggiunta di un tratto (che è un elemento unico). Ma ho bisogno di eseguire PHP 5.3 che non supporta i tratti.

C'è un modello che risolve questo problema?

EDIT 2: il punto è che non voglio cambiare il codice della libreria, posso estendere le sottoclassi e usarle nel codice client ma non voglio cambiare il codice nella libreria stessa (così posso aggiornare la libreria facilmente).

MODIFICA: vedi il codice semplificato sotto

abstract class SuperClass {
    protected function doMagic() { 
        ... I need to change this ...
    }

    abstract public function execute();
}

class SubClass1 extends SuperClass {
    protected public execute() {
        $this->doMagic();
        ... some other code ...
    }
}

class SubClass2 extends SuperClass {
    protected public execute() {
        $this->doMagic();
        ... some different code ...
    }
}
    
posta redhead 19.02.2013 - 22:16
fonte

3 risposte

1

Prima domanda: perché è necessario modificare la logica della classe astratta? Sembri indicare che non vuoi che nessuna delle sue attuali sottoclassi erediti le modifiche, quindi devo presumere che tu voglia scrivere nuove sottoclassi che lo faranno. Dato che le nuove sottoclassi non esistono ancora, aggiungi prima un po 'di riferimento indiretto:

abstract class SuperClass {
    protected function doMagic() { 
        ... I need to change this ...
    }

    abstract public function execute();
}

abstract class ExtendedSuperClass extends SuperClass {
    protected function doMagic() { 
        ... NEW CODE ...
    }
}


class SubClass1 extends SuperClass {
    protected public execute() {
        $this->doMagic();
        ... some other code ...
    }
}

class SubClass2 extends SuperClass {
    protected public execute() {
        $this->doMagic();
        ... some different code ...
    }
}

class SubClass3 extends ExtendedSuperClass {
    protected public execute() {
        $this->doMagic();
        ... yet more different code ...
    }
}

Ovvero, estendi la classe astratta con una nuova classe astratta, e fai in modo che le classi che hanno bisogno della nuova logica si estenda.

    
risposta data 19.02.2013 - 23:50
fonte
0

Le classi astratte dovrebbero essere scritte senza considerare le loro sottoclassi per evitare un accoppiamento stretto. Non so quale sia la tua situazione specifica, ma solitamente le classi astratte devono essere utilizzate per il polimorfismo, in cui ogni sottoclasse implementa un comportamento specifico attraverso un metodo astratto. Se ti ritrovi a cambiare codice all'interno della classe base che interromperà le sottoclassi, hai un problema di accoppiamento. Le classi base dovrebbero effettuare chiamate per abtracciare i metodi che le sottoclassi implementeranno. Inoltre, una sottoclasse dovrebbe limitare il numero di chiamate ai metodi principali.

    
risposta data 19.02.2013 - 22:54
fonte
0

Non vedo pattern di progettazione, ma un algoritmo.

Codice originale:

 abstract class SuperClass {
     protected function doMagic() { 
         ... I need to change this ...
     }

     abstract public function execute();
 } // class

 class SubClass1 extends SuperClass {
     protected public execute() {
         $this->doMagic();
         ... some other code ...
     }
 } // class

 class SubClass2 extends SuperClass {
     protected public execute() {
         $this->doMagic();
         ... some different code ...
     }
 } // class

Nuovo codice:

 abstract class SuperClass {
     protected $UseNewSpell = false;

     protected function OldSpell() {
        // put previous code here
     }

     protected function NewSpell() {
        // put new code here
     }

     protected function doMagic() { 
         if ($this->UseNewSpell) {
            $this->NewSpell();
         }
         else {
            $this->OldSpell();
         }                 
     }

     abstract public function execute();
 } // class

 class SubClass1 extends SuperClass {
     protected public execute() {
         $this->UseNewSpell = false;

         $this->doMagic();
         ... some other code ...
     }
 } // class

 class SubClass2 extends SuperClass {
     protected public execute() {
         $this->UseNewSpell = false;

         $this->doMagic();
         ... some different code ...
     }
 } // class
    
risposta data 19.02.2013 - 23:32
fonte

Leggi altre domande sui tag