Enum usecases: Replace switch/case blocks

at 2007-11-12 in Examples by friebe (0 comments)

When migrating parts of my photoblog's import scripts to command classes I stumbled upon the following block of code:

<?php 
switch
($group= $param->value('group')) {
case
'day': $strategy= new GroupByDayStrategy(); break;
case
'hour' : $strategy= new GroupByHourStrategy(); break;
default: throw
new IllegalArgumentException('No such grouping method "'.$group.'"');
}
?>

Except for putting this switch block into a GroupingStrategyFactory class to comply to DRY principles, this is basically OK, but I still wasn't happy having three (one interface, two concrete implementations) or four (for the case I'd add a factory) class files around for something this small.

Continue reading to see how this can be done with enums.

The original source
(shortened for brevity)

<?php 
// GroupingStrategy.class.php
interface GroupingStrategy
{
public
function groupFor(AlbumImage $image);
}

// GroupByHourStrategy.class.php
class GroupByHourStrategy extends Object implements GroupingStrategy {
public
function groupFor(AlbumImage $image) {
return
$image->exifData->dateTime->toString('Y-m-d H');
}
}

// GroupByDaytrategy.class.php
class GroupByDaytrategy extends Object implements GroupingStrategy {
public
function groupFor(AlbumImage $image) {
return
$image->exifData->dateTime->toString('Y-m-d');
}
}
?>

The enum way
First I replaced the interface by an abstract enumeration:
<?php 
abstract
class GroupingStrategy extends Enum {
public abstract
function groupFor(AlbumImage $image);
}
?>

The next step was to add the implementations:
<?php 
abstract
class GroupingStrategy extends Enum {
public
static $hour, $day;

static function __static() {
self::
$hour= newinstance(__CLASS__, array(0, 'hour'), '{
static function __static() { }
public function groupFor(AlbumImage $image) {
return $image->exifData->dateTime->toString("Y-m-d H");
}
}'
);
self::
$day= newinstance(__CLASS__, array(0, 'day'), '{
static function __static() { }
public function groupFor(AlbumImage $image) {
return $image->exifData->dateTime->toString("Y-m-d");
}
}'
);
}

public abstract
function groupFor(AlbumImage $image);
}
?>

...a factory method:
<?php 
public
static function forName($name) {
return parent::valueOf
(XPClass::forName(__CLASS__), $name);
}
?>

...and finally some boilerplate due to PHP limitations (see RFC #0132), PHP 5.3 will solve this with something they call "late static binding" (basically, static inheritance works in an intuitive way).

Please note the declaration is kind of clumsy but as you probably guessed this is due to enums not being natively supported by the PHP language:-)

Goal accomplished!
All code is one place now, and we have a very simple interface from the outside:
<?php 
$strategy= GroupingStrategy::forName($param->value('group'));
?>



Subscribe

You can subscribe to the XP framework's news by using RSS syndication.


Categories

News
General
PHP5
Announcements
RFCs
Further reading
Examples
Editorial
EASC
Experiments
Unittests
Databases

Related

Find related articles by a search for «Enum».