Como Implementar Design Patterns em TypeScript: Singleton
O que é o Design Pattern Singleton?
O design pattern Singleton é um padrão de projeto criacional que restringe a instanciação de uma classe a um único objeto. Ele garante que haja apenas uma instância da classe e fornece um ponto de acesso global a essa instância.
O padrão Singleton é útil em situações em que você deseja controlar a criação e o acesso de um determinado objeto. É comumente usado em cenários onde você precisa ter uma única instância de uma classe que pode ser acessada de várias partes do seu programa, como uma conexão de banco de dados, pools de threads, mecanismos de cache ou sistemas de log.
O padrão de projeto Singleton oferece várias vantagens:
Instância única: O padrão Singleton garante que haja apenas uma instância de uma classe em toda a aplicação. Isso pode ser útil quando você precisa coordenar o acesso a um recurso compartilhado ou manter um único estado em vários componentes.
Acesso global: O Singleton fornece um ponto de acesso global à instância, permitindo que qualquer parte do código acesse facilmente o mesmo objeto sem a necessidade de passar referências. Isso simplifica a comunicação entre diferentes partes da base de código.
Gerenciamento de recursos: Singletons são frequentemente usados para gerenciar recursos que devem ter um único ponto de controle. Por exemplo, uma conexão de banco de dados, acesso ao sistema de arquivos ou uma pool de threads. Ao encapsular o gerenciamento de recursos em um Singleton, você garante inicialização adequada, uso eficiente e descarte controlado de recursos.
Inicialização preguiçosa (lazy initialization): o padrão Singleton suporta inicialização preguiçosa (lazy initialization), o que significa que a instância é criada somente quando é solicitada pela primeira vez. Isso pode ser benéfico para desempenho e uso de memória, especialmente em cenários em que a instância pode não ser necessária durante todo o ciclo de vida da aplicação.
Segurança da thread: Quando implementado corretamente, o padrão Singleton pode fornecer segurança para a thread. Ao usar técnicas como bloqueio de verificação dupla ou inicializar a instância de maneira segura para threads, você pode garantir que a instância Singleton seja criada corretamente, mesmo em um ambiente multithread.
Fácil de usar e manter: o padrão Singleton fornece uma maneira direta de acessar e gerenciar uma única instância. Evita a necessidade de lógica de instanciação complexa ou passagem de referências entre objetos. Isso melhora a legibilidade do código, a capacidade de manutenção e a facilidade de uso.
Apesar dessas vantagens, é importante usar o padrão Singleton criteriosamente e considerar suas possíveis desvantagens, como introduzir o estado global, tornar os testes mais desafiadores e potencialmente criar um acoplamento rígido entre os componentes. O design cuidadoso e a consideração de alternativas são necessários para garantir que os benefícios superem as desvantagens em um determinado cenário.
Como Implementar o Singleton
Digamos que temos uma classe Logger
que lida com mensagens de registro em toda a aplicação. Queremos garantir que haja apenas uma instância da classe Logger
que possa ser acessada de diferentes partes de nossa base de código.
class Logger {
private static instance: Logger;
private constructor() {
// Private constructor to prevent instantiation from outside the class
}
public static getInstance(): Logger {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
public log(message: string): void {
console.log(`[LOG]: ${message}`);
}
}
export default Logger.getInstance();
Neste exemplo, a classe Logger
possui um construtor privado, impedindo a instanciação direta de fora da classe. O método getInstance()
fornece uma maneira de acessar a única instância da classe Logger
. Se a instância não existir, ela cria uma nova; caso contrário, ele retorna a instância existente.
Usando o método getInstance()
, podemos garantir que todas as referências à classe Logger
apontem para a mesma instância.
Observe que o TypeScript oferece suporte ao construtor privado e aos membros estáticos, facilitando a implementação do padrão Singleton.