Yes, objects can be added/deleted etc so perhaps it is a queue after all. Just to confuse matters further, I've taken to calling it "DynamicEngine".
Here's the latest version & some notes. In a few weeks or so I'll maybe stick up a few pages somewhere showing how it can be used as the core of a php framework.
CLASS: DynamicEngine
A variation on the factory theme. DE is intended to assist some kind of manager-type class: loads a bunch of objects in a processing pipe or queue.
(1) loaded objects can reprogram the objects list
(2) objects in the pipe are both observers of and observable to each other
(3) the $manager object is also an observer of pipe objects
DE loads classes defined in an $objects_list array. The array contains names of classes to load and their script paths eg:
Code: Select all
$objects_list[0]['class'] = 'Foo';
$objects_list[0]['script'] = 'path/to/file1.php';
$objects_list[1]['class'] = 'Bar';
$objects_list[1]['script'] = 'path/to/file2.php';
It's occasionally useful to pass args to individual objects via the meta data array- just add another key (see loadObjects).
The reprogrammable behaviour is obtained by allowing objects in the list to edit the array while it is being looped over. They may add other objects, load themselves again for another go, reset the entire list, etc. Obviously, a feedback mechanism creates a risk of infinite loops - DE won't stop you doing that should you try.
Chained messages (ie a message triggered in repsonse to receipt of another message) carry the same risk.
An array of args can be passed from $manager for use by pipe objects (see getArgs). At present, that - and $manager observation of pipe objects - is as far as any interaction between the two goes. A minor re-write could pass the $manager itself to pipe objects, should they require access to $manager properties or methods.
The reprogrammable mechanism & message system could possibly be used to create quite complex behaviours. Haven't really explored that as yet. The whole thing originated from amateur musings on AI (which went nowhere). I'm hoping it will be a flexible, powerful tool but time will tell just how easy it is to get along with.
Code: Select all
class DynamicEngine
{
// public
var $args;
/*
param (object) $manager - the object assisted by DE
*/
function DynamicEngine(&$manager)
{
$this->manager =& $manager;
$this->args =& $manager->getArgs();
}
/*
(1) instantiates classes listed in the $objects_list array,
(2) attach observables
(3) tells each object to "start" (docs: PipeObjects interface)
NB: do not broadcast chained messages from pipe object constructors (object isn't registered as observer at this stage, hence chained messages cannot work).
*/
function loadObjects()
{
while(!is_null($object_meta = array_shift($this->objects_list)))
{
include_once($object_meta['script']);
$class = $object_meta['class'];
$ob =& new $class($this, $object_meta);
$this->pipe_objects[$class] =& $ob; // attach observable
$ob->start();
}
}
/*
OBJECTS LIST
Methods to set $objects_list meta data or edit array elements.
Pipe objects are free to use these methods to delete
objects from the list, add new objects, or even load
themselves again for another go.
If you use that feature, watch out for infinite loops...
param (array) $objects_list meta data eg:
*/
// destructive set / reset
function setObjectsList($objects_list)
{
$this->objects_list = $objects_list;
}
// add to start of list (non-destructive)
function prependObjects($objects_list)
{
foreach($objects_list as $value)
{
array_unshift($this->objects_list, $value);
}
}
// add to end of list (non-destructive)
function appendObjects($objects_list)
{
foreach($objects_list as $value)
{
array_push($this->objects_list, $value);
}
}
/*
ARGS
Pass $args obtained from $manager through to pipe objects.
return (array) $args
*/
function &getArgs()
{
return $this->args;
}
/*
NOTIFY OBSERVERS
*/
/*
A "broadcast" message on pipe objects channel.
Received by all instantiated (!) pipe objects.
param (string) $type
param (mixed) $payload
*/
function notifyPipeObjects($type, &$payload)
{
foreach(array_keys($this->pipe_objects) as $class)
{
$this->pipe_objects[$class]->listen($type, $payload);
}
}
/*
"Narrow-cast" messages on $manager channel
param (string) $type
param (mixed) $payload
*/
function notifyManager($type, &$payload)
{
$this->manager->listen($type, $payload);
}
}
PS: messages contain a $type and $payload.
$type is used to dynamically call a method in the observer; $payload is the, er, message payload - string, array, object - whatever.