A resposta abaixo está errada, mas vou mantê-la para que outras pessoas aprendam com ela (veja abaixo)
Em ExampleA
, você pode usar a mesma Config
instância em várias classes. No entanto, se houver apenas uma Config
instância em todo o aplicativo, considere aplicar o padrão Singleton Config
para evitar ter várias instâncias de Config
. E se Config
for um Singleton, você pode fazer o seguinte:
class ExampleA
{
private $config;
public function __construct()
{
$this->config = Config->getInstance();
}
}
$exampleA = new ExampleA();
Por ExampleB
outro lado, você sempre terá uma instância separada de Config
para cada instância de ExampleB
.
Qual versão você deve aplicar realmente depende de como o aplicativo tratará instâncias de Config
:
- se cada instância de
ExampleX
deve ter uma instância separada de Config
, vá com ExampleB
;
- se cada instância de
ExampleX
compartilhar uma (e apenas uma) instância de Config
use ExampleA with Config Singleton
;
- se instâncias de
ExampleX
podem usar diferentes instâncias de Config
, permaneça com ExampleA
.
Por que converter Config
em um Singleton está errado:
Devo admitir que só aprendi sobre o padrão Singleton ontem (lendo o livro Head First de padrões de design). Ingenuamente, eu o apliquei neste exemplo, mas, como muitos apontaram, de uma maneira são outras (algumas foram mais enigmáticas e apenas disseram "Você está fazendo errado!"), Essa não é uma boa ideia. Portanto, para impedir que outras pessoas cometam o mesmo erro que eu cometi, segue um resumo de por que o padrão Singleton pode ser prejudicial (com base nos comentários e no que descobri pesquisando no Google):
Se ExampleA
recuperar sua própria referência à Config
instância, as classes serão fortemente acopladas. Não haverá como ExampleA
usar uma versão diferente de Config
(por exemplo, uma subclasse). Isso é horrível se você deseja testar ExampleA
usando uma instância de mock-up, Config
pois não há como fornecê-la ExampleA
.
A premissa de que haverá uma, e apenas uma, instância de Config
talvez vale agora , mas você nem sempre pode ter certeza de que o mesmo será válido no futuro . Se em algum momento posterior se verificar que várias instâncias de Config
serão desejáveis, não há como conseguir isso sem reescrever o código.
Mesmo que a única instância de Config
talvez seja verdadeira por toda a eternidade, pode acontecer que você queira usar algumas subclasses de Config
(embora ainda tenha apenas uma instância). Mas, como o código obtém diretamente a instância por meio getInstance()
de Config
, que é um static
método, não há como obter a subclasse. Novamente, o código deve ser reescrito.
O fato de que os ExampleA
usos Config
serão ocultados, pelo menos ao visualizar a API de ExampleA
. Isso pode ou não ser uma coisa ruim, mas pessoalmente sinto que isso parece uma desvantagem; por exemplo, ao manter, não há uma maneira simples de descobrir quais classes serão afetadas pelas alterações Config
sem examinar a implementação de todas as outras classes.
Mesmo que o fato de ExampleA
usar um Singleton Config
não seja um problema em si, ele ainda pode se tornar um problema do ponto de vista de teste. Os objetos Singleton terão o estado que persistirá até o término do aplicativo. Isso pode ser um problema ao executar testes de unidade, pois você deseja que um teste seja isolado de outro (ou seja, que a execução de um teste não afete o resultado de outro). Para corrigir isso, o objeto Singleton deve ser destruído entre cada execução de teste (possivelmente tendo que reiniciar o aplicativo inteiro), o que pode levar muito tempo (sem mencionar tedioso e irritante).
Dito isto, fico feliz por ter cometido esse erro aqui e não na implementação de um aplicativo real. Na verdade, eu estava pensando em reescrever meu código mais recente para usar o padrão Singleton para algumas das classes. Embora eu pudesse reverter facilmente as alterações (tudo é armazenado em um SVN, é claro), ainda assim eu teria perdido tempo fazendo isso.