Non sono un appassionato di pattern e ne capisco ben poco, ma vorrei porre alcune osservazioni e dare il mio contributo. Hai di fatto creato un oggetto costante ossia essendo le classi delle definizioni di tipi e raltive operazioni possibli, non fai altro che definire uno stato per la classe impedendone la modifica. Ma essendo una costante, non dovrei ottenere sempre lo stesso oggetto, a parità di parametri in ingresso, all'atto della creazione? In altre parole il valore 10 è tale a prescindere dalla variabile a cui è assegnato così come uno stato costate di un oggetto dovrebbe essere tale aprescindere dall'oggetto istanziato ossia l'istanza è sempre la stessa.
Io avrei svolto il compitino in questo modo:
Codice PHP:
<?php
class OggettoCostante {
private static $gliOggetti = [];
private $iDati = [];
/**
* Crea un nuovo oggetto costante. In $valori vanno specificate coppie
* [nomeProprietà => valore, ...]. Le proprietà saranno poi accessibili
* tramite la sintassi $oggetto->nomeProprietà in sola lettaura
* @param array $valori
* @return type
*/
public static function creaNuovoOggetto(array $valori) {
$hash = hash("sha256", serialize($valori)); //tengo le dita incrociate
if (!isset(self::$gliOggetti[$hash]))
self::$gliOggetti[$hash] = new OggettoCostante($valori);
return self::$gliOggetti[$hash];
}
private function __construct(array $valori) {
foreach ($valori as $nomeProprieta => $valore) {
if (is_object($valore))
$valore = clone $valore;
$this->iDati[$nomeProprieta] = $valore;
}
}
public function __get($name) {
if (isset($this->iDati[$name]))
return $this->iDati[$name];
throw new Exception("La proprieta non e' definita");
}
public function __set($name, $value) {
throw new Exception("Non e' ammessa la modifica dello stato dell'oggetto");
;
}
}
final class URL extends OggettoCostante {
/**
* Crea un nuovo oggetto url costante. Il parametro è un array del tipo:
* ['url' => 'http://www.google.com']
* @param array $url
* @throws Exception
*/
public static function creaNuovoOggetto(array $url) {
if (!isset($url['url']) or !filter_var($url['url'], FILTER_VALIDATE_URL, array(FILTER_FLAG_SCHEME_REQUIRED, FILTER_FLAG_HOST_REQUIRED))) {
throw new Exception("Parametro non correttamente formattato o url non valido.");
}
$purl = parse_url($url['url']);
$scheme = $purl['scheme'];
$host = $purl['host'];
$path = (isset($purl['path'])) ? $purl['path'] : 'undefined';
$query = (isset($purl['query'])) ? $purl['query'] : 'undefined';
return parent::creaNuovoOggetto(array('url' => $url['url'], 'scheme' => $scheme, 'host' => $host, 'path' => $path, 'query' => $query));
}
}
//script di test
try {
$test = URL::creaNuovoOggetto(['url' => 'h*t*t*p://www.test.it/index.php?q=paperino']);
$test1 = URL::creaNuovoOggetto(['url' => 'h*t*t*p://www.test.it/index.php?q=paperino']);
$test2 = URL::creaNuovoOggetto(['url' => 'h*t*t*p://www.test.com/index.php?q=paperino']);
var_dump($test == $test1);
var_dump($test2 == $test1);
echo $test->url . '<br>' . $test->scheme . '<br>' . $test->host . '<br>' . $test->path . '<br>' . $test->query . '<br>';
$test->url = 'Pippo';
} catch (Exception $e) {
echo $e->getMessage();
}
?>
L'output dello script di test è:
codice:
boolean true
boolean false
h*t*t*p*://w*w*w*.test.it/index.php?q=paperino
http
w*w*w*.test.it
/index.php
q=paperino
Non e' ammessa la modifica dello stato dell'oggetto
in questo modo hai la possibilità di:
1) accedere alle prorpietà direttametne tramite il loro nome senza permetterene la modifica
2) poter verificare che lo stato sia lo stesso per due oggetti OggettoCostante, e per ereditarità URL, semplicemente utlizzando l'operatore di confronto == dato che oggetti con uguale stato utilizzano lo stesso oggetto
in più OggettoCostante è sufficientemente generico da poter essere utilizzato e riutilizzato in ogni circostanza, direttamente o per specializzazione come nel caso di URL riducendo il codice necessario e semplificandone la stesura.
Ovviamente il tutto è opinabile sebbene questo sia il mio metodo.
Nota gli * in più sono per nascondere gli url altrimenti non potevo postare