Amb PHP només podem tenir un sol constructor i això sovint és un limitació important. Per exemple imagineu un objecte Time:
$time = new Time("11:45"); $time = new Time(11, 45); $minutesSinceMidnight = 705; $time = new Time($minutesSinceMidnight);
Les tres opcions poden ser interessants no? (vegeu Carbon) Perpo amb PHP cal fer tot el codi en un sol constructor i el codi serà lleig:
final class Time { private $hours, $minutes; public function __construct($timeOrHours, $minutes = null) { if(is_string($timeOrHours) && is_null($minutes)) { list($this->hours, $this->minutes) = explode($timeOrHours, ':', 2); } else { $this->hours = $timeOrHours; $this->minutes = $minutes; } } }
I anirà empitjorant quantes més opcions afegim! Un solució és crear constructors amb nom vegeu un exemple
<?php final class Time { private $hours, $minutes; public function __construct($hours, $minutes) { $this->hours = (int) $hours; $this->minutes = (int) $minutes; } public static function fromString($time) { list($hours, $minutes) = explode($time, ':', 2); return new Time($hours, $minutes); } public static function fromMinutesSinceMidnight($minutesSinceMidnight) { $hours = floor($minutesSinceMidnight / 60); $minutes = $minutesSinceMidnight % 60; return new Time($hours, $minutes); } }
Ara cada mètode compleix amb el Single Responsibility Principle. La interfície pública és clara i comprensible i les implementacions són senzilles i directes.
De fet encara podem anar més enllà i eliminar el constructor i forçar a utilitzar els named constructors:
<?php final class Time { private $hours, $minutes; // We don't remove the empty constructor because it still needs to be private private function __construct(){} public static function fromValues($hours, $minutes) { $time = new Time; $time->hours = $hours; $time->minutes = $minutes; return $time; } public static function fromString($time) { list($hours, $minutes) = explode($time, ':', 2); return new Time($hours, $minutes); } public static function fromMinutesSinceMidnight($minutesSinceMidnight) { $hours = floor($minutesSinceMidnight / 60); $minutes = $minutesSinceMidnight % 60; return new Time($hours, $minutes); } }
Un exemple ([1]):
<?php class Student { protected $firstName; protected $lastName; // etc. /** * Constructor */ public function __construct() { // allocate your stuff } /** * Static constructor / factory */ public static function create() { $instance = new self(); return $instance; } /** * FirstName setter - fluent style */ public function setFirstName( $firstName) { $this->firstName = $firstName; return $this; } /** * LastName setter - fluent style */ public function setLastName( $lastName) { $this->lastName = $lastName; return $this; } } // create instance $student= Student::create()->setFirstName("John")->setLastName("Doe"); // see result var_dump($student);
Vegeu Factory pattern s'assembla molt