I have a question which is sonewhat more of a design question. I have a class which defines a bunch of functions. However, I want that the behaviour of some functions are changeable during runtime - or at least working like a plugin interface during design time. eg:
class MyClass {
public function doSomething();
}
$obj = new MyClass();
// PSEUDO CODE
$obj->doSomething = doSomethingElse;
$obj->doSomething(); // does something else
I had various Ideas how to implement something like this in "real" code. However, I am not quite sure, which is the right way to go. I first thought I could use an Interface for this purpose.
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!
This approach could be expanded to not have the doSomething provider passed as a parameter, but to set it either as an object member or even class member. However, I did not like that I have to create an instance of n class which does not even contain a single member variable and the only method could easily be a static class function. There's just no need for an object at that point imo. I then was going to try to use function variables - but I'd fall out of OOP then, which I didn't like either. My questions are: which is the best way to implement a system like I described? Which approach would you try or use? Is there anything obvious I might not have thought of? Or should I just go with the interface approach and my bad feeling about instanciating 'bodyless' objects is just nerd preciousness?! I'm curious about your answers!
Edit:
Because I'm really interested in clarifying if this actually is (or should be) a State or a Strategy Pattern, I'll go into some more detail on the implementation. I have a base class of collections from which I derive different specific implementations. I want to be able to select a single element from any specific implementation - however, I want to be able dynamically alter how this element is selected from the collection, eg:
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
This is basicly what I want to achieve. Is this now more a strategy pattern implementation or the state pattern - albeit I used the term strategy because it fits more in this case anyway. As far as I understand the strategy and state pattern a basicly the same, except their intent is different. The link provided by Gordon states that a state pattern's intent is "Allow an object to alter its behavior when its internal state changes" - but this it not the case here. What I want is to be able to tell my MyCollection class "use this or that algorithm to give me an element" - not "give me an element using an algorithm that you determine through your own state". Hope someone can clarify this!
Best regards, Daniel