Realizei uma implementação do exercício de "requisições" do padrão Chain of responsibility usando uma classe abstrata.
Logo me ocorreu de saber a opinião de vocês sobre tal implementação.
E nesse tipo de implementação em específico, me parece ter um template method formando um chain.
O que acham, estou errado, meio certo, certo?
<?php
class Conta
{
    public $saldo = 0.0;
    public $titular = "";
    public function __construct($saldo, $titular)
    {
        $this->saldo = $saldo;
        $this->titular = $titular;
    }
}
class Formato 
{
    public static $XML = "XML";
    public static $CSV = "CSV";
    public static $PORCENTO = "PORCENTO";
}
class Requisicao 
{
      private $formato;
      public function __construct($formato)
      {
          $this->formato = $formato;
      }
      public  function getFormato()
      {
          return $this->formato;
      }
}
abstract class Resposta
{
    protected $tipoResposta;    
    public $proxima;
    public function enviarResposta(Conta $conta, Requisicao $requisicao)
    {
        if($requisicao->getFormato() != $this->tipoResposta && $this->proxima != NULL)
            return $this->proxima->enviarResposta($conta, $requisicao);
        return $this->responder($conta, $requisicao);
    }
    public function setProxima(Resposta $resposta)
    {
        return $this->proxima = $resposta;
    }
    protected abstract function responder(Conta $conta, Requisicao $requisicao);
}
class RespostaXml extends Resposta
{
    public $tipoResposta = "XML";
    public function responder(Conta $conta, Requisicao $requisicao)
    {
        $resposta = "";
        $resposta .= "<conta>";
        $resposta .= "<titular>";
        $resposta .= $conta->titular;
        $resposta .= "</titular>";
        $resposta .= "<saldo>";
        $resposta .= $conta->saldo;
        $resposta .= "</saldo>";
        $resposta .= "</conta>";
        return $resposta;
    }    
}
class RespostaCsv extends Resposta
{
    public $tipoResposta = "CSV";
    public function responder(Conta $conta, Requisicao $requisicao)
    {
        $resposta = "";
        $resposta .= $conta->titular;
        $resposta .= ";";
        $resposta .= $conta->saldo;
        $resposta .= ";";
        return $resposta;
    }
}
class RespostaPorcento extends Resposta
{
    public $tipoResposta = "PORCENTO";
    public function responder(Conta $conta, Requisicao $requisicao)
    {
        $resposta = "";
        $resposta .= $conta->titular;
        $resposta .= "%";
        $resposta .= $conta->saldo;
        $resposta .= "%";
        return $resposta;
    }
}
class RespostaSemFormato extends Resposta
{
    public $proxima = NULL;
    public function responder(Conta $conta, Requisicao $requisicao)
    {
        $resposta = "";
        return $resposta;
    }
}
class RespondeRequisicao
{
    public function resposta(Requisicao $requisicao, Conta $conta)
    {
        $respostaXml = new RespostaXml();
        $respostaCsv = new RespostaCsv();
        $respostaPorcento = new RespostaPorcento();
        $semResposta = new RespostaSemFormato();
        $respostaXml->setProxima($respostaCsv);
        $respostaCsv->setProxima($respostaPorcento);
        $respostaPorcento->setProxima($semResposta);
        return $respostaXml->enviarResposta($conta, $requisicao);
    }
}
$formato = Formato::$PORCENTO;
$conta = new Conta(500.00, "Eduardo Cesar");
$requisicao = new Requisicao($formato);
$responder = new RespondeRequisicao();
var_dump($responder->resposta($requisicao, $conta)); 
            