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