Ho una domanda che è un po 'più una domanda di design. Ho una classe che definisce un sacco di funzioni. Tuttavia, voglio che il comportamento di alcune funzioni sia modificabile durante il runtime - o almeno funzioni come un'interfaccia plugin durante la fase di progettazione. es:Classi PHP polimorfici/plug-in
class MyClass {
public function doSomething();
}
$obj = new MyClass();
// PSEUDO CODE
$obj->doSomething = doSomethingElse;
$obj->doSomething(); // does something else
Ho avuto varie idee su come implementare qualcosa di simile nel codice "reale". Tuttavia, non ne sono del tutto sicuro, qual è la strada giusta da percorrere. Per prima cosa ho pensato che potrei usare un'interfaccia per questo scopo.
interface IDoSomethingInterface {
public function doSomething();
}
class DoSomethingClass implements IDoSomethingInterface
{
public function doSomething()
{
// I do something!
}
}
class DoSomethingElseClass implements IDoSomethingInterface
{
public function doSomething()
{
// I actually do something else!
}
}
class MyClass {
public doSomething(IDoSomething $doSomethingProvider)
{
$doSomethingProvider->doSomething();
}
}
$obj = new MyClass();
$doSomethingProvider = new DoSomethingClass();
$doSomethingElseProvider = new DoSomethingElseClass();
$obj->doSomething($doSomethingProvider); // I do something!
$obj->doSomething($doSomethingElseProvider); // I do something else!
Questo approccio potrebbe essere esteso per non avere il provider doSomething passato come parametro, ma per impostarlo sia membro come oggetto o membro della classe. Tuttavia, non mi piaceva che dovessi creare un'istanza di n classe che non contenesse nemmeno una singola variabile membro e l'unico metodo potrebbe facilmente essere una funzione di classe statica. A questo punto non c'è più bisogno di un oggetto. Poi ho provato a utilizzare le variabili di funzione, ma non sarei riuscito a rientrare in OOP, cosa che a me non piaceva. Le mie domande sono: qual è il modo migliore per implementare un sistema come quello che ho descritto? Quale approccio vorresti provare o usare? C'è qualcosa di ovvio a cui non avrei pensato? O dovrei semplicemente andare con l'approccio dell'interfaccia e la mia cattiva sensazione di instanciare oggetti "senza corpo" è solo una preziosa nullità ?! Sono curioso delle tue risposte!
Edit:
Perché io sono veramente interessato a chiarire se questo in realtà è (o dovrebbe essere) uno Stato o di un modello di strategia, andrò in qualche modo più dettagliato sull'attuazione. Ho una classe base di collezioni da cui ricavo diverse implementazioni specifiche. Voglio essere in grado di selezionare un singolo elemento da qualsiasi specifica implementazione - tuttavia, voglio essere in grado per modificare dinamicamente come questo elemento è selezionato dalla collezione, ad esempio:
class MyCollection implements Countable, ArrayAcces, Iterator
{
// Collection Implementation
public function select(ISelectionStrategy $strategy)
{
return $strategy->select($this);
}
}
interface ISelectionStrategy
{
public function select(MyCollection $collection);
}
class AlphaSelectionStrategy implements ISelectionStrategy
{
public function select(MyCollection $collection);
{
reset($collection);
if (current($collection))
return current($collection);
else
return null;
}
}
class OmegaSelectionStrategy implements ISelectionStrategy
{
public function select(MyCollection $collection)
{
end($collection);
if (current($collection))
return current($collection)
else
return null;
}
}
class RandomSelectionStrategy implements ISelectionStrategy
{
public function select(MyCollection $collection)
{
if (!count($collection))
return null;
$rand = rand(0, count($collection)-1);
reset($collection);
while($rand-- > 0)
{
next($collection);
}
return current($collection);
}
}
$collection = new MyCollection();
$randomStrategy = new RandomSelectionStrategy();
$alphaStrategy = new AlphaSelectionStrategy();
$omegaStrategy = new OmegaSelectionStrategy();
$collection->select($alphaStrategy); // return first element, or null if none
$collection->select($omegaStrategy); // return last element, or null if none
$collection->select($randomStrategy); // return random element, or null if none
Questo è fondamentalmente ciò che voglio raggiungere . Si tratta ora di una implementazione del modello di strategia o del modello di stato, anche se ho usato il termine strategia perché si adatta di più in questo caso comunque. Per quanto ne so, la strategia e lo schema di stato sono fondamentalmente uguali, tranne che il loro intento è diverso. Il collegamento fornito da Gordon afferma che l'intenzione di un modello di stato è "Permetti ad un oggetto di alterare il suo comportamento quando il suo stato interno cambia" - ma questo non è il caso qui. Quello che voglio è essere in grado di dire alla mia classe MyCollection "usa questo o quell'algoritmo per darmi un elemento" - non "dammi un elemento usando un algoritmo che determini attraverso il tuo stato". Spero che qualcuno possa chiarire questo!
Con i migliori saluti, Daniel
+1, quella faccina sarà la mia fine. xP –
Bene, hai già risposto alla tua domanda. Non vuoi gestire gli stati. Vuoi scambiare singoli comportamenti, quindi la strategia è appropriata. Su un sidenote, dal momento che sembri essere tedesco, posso consigliare il libro phpdesignpatterns.de – Gordon