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 interface GroupingStrategy { public function groupFor(AlbumImage $image); } class GroupByHourStrategy extends Object implements GroupingStrategy { public function groupFor(AlbumImage $image) { return $image->exifData->dateTime->toString('Y-m-d H'); } } 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.
CategoriesNews General PHP5 Announcements RFCs Further reading Examples Editorial EASC Experiments Unittests Databases
RelatedFind related articles by a search for «Enum».
|