Tengo una pregunta que es más una cuestión de diseño. Tengo una clase que define un grupo de funciones. Sin embargo, quiero que el comportamiento de algunas funciones se modifique durante el tiempo de ejecución, o al menos funcione como una interfaz de complemento durante el tiempo de diseño. por ejemplo:Clases de PHP polimórficas/conectables
class MyClass {
public function doSomething();
}
$obj = new MyClass();
// PSEUDO CODE
$obj->doSomething = doSomethingElse;
$obj->doSomething(); // does something else
Tenía varias ideas sobre cómo implementar algo como esto en el código "real". Sin embargo, no estoy seguro, cuál es el camino correcto a seguir. Primero pensé que podría usar una interfaz para este propósito.
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!
Este enfoque podría ampliarse para no tiene el proveedor de doSomething pasado como parámetro, pero para ajustar ya sea como un miembro de objeto o incluso miembro de la clase. Sin embargo, no me gustó que tuviera que crear una instancia de n clase que ni siquiera contenga una sola variable miembro y el único método podría ser fácilmente una función de clase estática. Simplemente no hay necesidad de un objeto en ese punto. Luego iba a tratar de usar variables de función, pero me caería de OOP entonces, lo que tampoco me gustó. Mis preguntas son: ¿cuál es la mejor manera de implementar un sistema como el que describí? ¿Qué enfoque probarías o usarías? ¿Hay algo obvio que quizás no haya pensado? ¿O debería ir con el enfoque de interfaz y mi mal presentimiento sobre la instanciación de objetos "sin cuerpo" es simplemente preciosismo nerd ?! ¡Tengo curiosidad por tus respuestas!
Editar:
Porque estoy realmente interesado en aclarar si esto realmente es (o debería ser) un Estado o un patrón de estrategia, voy a entrar en más detalle sobre la aplicación. Tengo una clase base de colecciones de la cual derivo diferentes implementaciones específicas. Quiero ser capaz de seleccionar un solo elemento de cualquier aplicación específica - sin embargo, yo quiero ser capaz dinámicamente alterar cómo este elemento se selecciona de la colección, por ejemplo:
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
Esto es básicamente lo que quiero lograr . ¿Es esto más una implementación de un patrón de estrategia o el patrón de estado, aunque utilicé el término estrategia porque, de todos modos, encaja más en este caso? Por lo que yo entiendo, la estrategia y el patrón de estado son básicamente los mismos, excepto que su intención es diferente. El enlace proporcionado por Gordon establece que la intención de un patrón de estado es "Permitir que un objeto modifique su comportamiento cuando su estado interno cambia", pero este no es el caso aquí. Lo que quiero es poder decirle a mi clase MyCollection "usar este o aquel algoritmo para darme un elemento", no "darme un elemento usando un algoritmo que usted determine a través de su propio estado". Espero que alguien pueda aclarar esto!
Saludos cordiales, Daniel
+1, Ese cariño va a ser mi final. xP –
Bueno, usted mismo ya respondió su pregunta. No desea administrar estados. Desea intercambiar comportamientos individuales, por lo que la estrategia es apropiada. En una nota al margen, ya que parece ser alemán, puedo recomendar el libro phpdesignpatterns.de – Gordon