DEV Community

Cover image for Singleton ou Observable? A Escolha Errada Pode Custar Sua Promoção!
Cláudio Filipe Lima Rapôso
Cláudio Filipe Lima Rapôso

Posted on

Singleton ou Observable? A Escolha Errada Pode Custar Sua Promoção!

Os padrões de projeto são fundamentais na criação de software bem estruturado e fácil de manter. Entre eles, o Singleton e o Observable são frequentemente utilizados em cenários que exigem controle de estado global e comunicação entre diferentes partes do sistema. Neste artigo, vamos explorar como esses dois padrões funcionam, quando utilizá-los, suas diferenças e fornecer exemplos práticos de como implementá-los.

O que é o Singleton?

O Singleton Pattern é um padrão de design criacional que assegura que uma classe tenha apenas uma instância e fornece um ponto global de acesso a essa instância. Esse padrão é útil quando você precisa de um objeto único em toda a aplicação, como em configurações globais, conexão com banco de dados, ou gerenciamento de logs.

Como Funciona o Singleton?

A principal característica do Singleton é que ele restringe a instância da classe a um único objeto, garantindo que todas as requisições de instância retornem o mesmo objeto. Para isso, o padrão normalmente utiliza um método estático que cria a instância apenas quando ela é solicitada pela primeira vez, garantindo a criação única e o uso do objeto em todo o sistema.

No diagrama abaixo, a sequência mostra como a instância do Singleton é criada e acessada, garantindo que seja única.

Diagrama de Sequência do Singleton

O diagrama de sequência do Singleton ilustra o fluxo de interação entre o cliente e a classe Singleton. O processo começa com o cliente chamando o método estático getInstance() para obter a instância do Singleton. Se a instância ainda não foi criada, o Singleton cria uma nova instância e a retorna. Quando o cliente chama novamente o método getInstance(), a mesma instância é retornada, garantindo que exista apenas uma instância do objeto Singleton durante toda a execução do programa.

Exemplo de Uso - Singleton em TypeScript

class Singleton {
    private static instance: Singleton;

    private constructor() { }

    // Método para acessar a instância única
    public static getInstance(): Singleton {
        if (!Singleton.instance) {
            Singleton.instance = new Singleton();
        }
        return Singleton.instance;
    }

    public showMessage(): string {
        return "Esta é a única instância!";
    }
}

// Uso do Singleton
const instance1 = Singleton.getInstance();
console.log(instance1.showMessage()); // "Esta é a única instância!"
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true
Enter fullscreen mode Exit fullscreen mode

Quando Usar o Singleton?

  • Configurações globais: quando você precisa de uma instância única para armazenar configurações de sistema, como variáveis de ambiente.
  • Gestão de conexões: por exemplo, para gerenciar conexões com um banco de dados ou um servidor de API.
  • Gerenciamento de recursos: quando é necessário controlar o acesso a um recurso exclusivo, como um logger ou cache.

O que é o Observable?

O Observable Pattern é um padrão de design comportamental que define uma dependência de um-para-muitos entre objetos. Ou seja, quando o estado de um objeto (o "subject") muda, todos os seus dependentes (os "observers") são notificados automaticamente. Este padrão é muito utilizado em sistemas onde eventos e mudanças de estado precisam ser propagados entre diversos componentes, como interfaces gráficas ou sistemas de monitoramento.

Como Funciona o Observable?

O padrão Observable permite que objetos "observem" as mudanças de estado de um objeto e reajam a essas mudanças. O padrão se baseia em três componentes principais:

  1. Subject: o objeto que mantém o estado e envia notificações aos observers.
  2. Observer: objetos que estão interessados nas mudanças de estado do Subject.
  3. Subscription: um mecanismo que permite ao Observer se inscrever ou cancelar a inscrição nas notificações do Subject.

Diagrama de Sequência do Observable

O diagrama de sequência do Observable demonstra como o padrão funciona com múltiplos observadores. O Subject (ou objeto observado) notifica todos os Observers registrados quando ocorre uma mudança de estado. Cada Observer reage à notificação, realizando as ações necessárias com base nas informações recebidas. O processo de notificação é propagado de forma que todos os observadores sejam atualizados simultaneamente, mantendo-os sincronizados com o estado do Subject. Esse padrão é útil quando há múltiplos componentes ou partes do sistema que precisam ser informados sobre mudanças no estado de um objeto.

Exemplo de Uso - Observable em TypeScript

// Interface Observer
interface Observer {
    update(message: string): void;
}

// Classe Subject
class Observable {
    private observers: Observer[] = [];

    // Método para adicionar observers
    public addObserver(observer: Observer): void {
        this.observers.push(observer);
    }

    // Método para remover observers
    public removeObserver(observer: Observer): void {
        const index = this.observers.indexOf(observer);
        if (index !== -1) {
            this.observers.splice(index, 1);
        }
    }

    // Método para notificar observers
    public notifyObservers(message: string): void {
        this.observers.forEach(observer => observer.update(message));
    }
}

// Classe Observer concreta
class ConcreteObserver implements Observer {
    private name: string;

    constructor(name: string) {
        this.name = name;
    }

    public update(message: string): void {
        console.log(`${this.name} recebeu a mensagem: ${message}`);
    }
}

// Uso do Observable
const observable = new Observable();

const observer1 = new ConcreteObserver("Observer 1");
const observer2 = new ConcreteObserver("Observer 2");

observable.addObserver(observer1);
observable.addObserver(observer2);

observable.notifyObservers("Mudança no sistema!");

observable.removeObserver(observer1);

observable.notifyObservers("Nova mudança!");
Enter fullscreen mode Exit fullscreen mode

Quando Usar o Observable?

  • Eventos em interfaces gráficas: para reagir a cliques de botões, mudanças de campos, ou atualizações de tela.
  • Notificação de mudanças de estado: quando diversos componentes precisam ser informados sobre alterações em um objeto.
  • Modelagem de fluxo de dados reativo: em sistemas onde há propagação de dados ou eventos entre múltiplos sistemas, como em aplicações baseadas em eventos.

Diferenças entre Singleton e Observable

Embora ambos os padrões sirvam para gerenciar objetos de forma controlada, suas finalidades e comportamentos são bem diferentes:

Característica Singleton Observable
Objetivo Garantir que uma classe tenha apenas uma instância. Notificar múltiplos objetos sobre mudanças de estado.
Instância Apenas uma instância é criada e compartilhada. Vários objetos podem ser observadores de um único sujeito.
Uso principal Gerenciamento de recursos exclusivos. Notificação de eventos e mudanças de estado.
Exemplo de uso Gerenciamento de logs ou configuração global. Atualização de interfaces gráficas ou propagação de eventos.

Conclusão

Os padrões Singleton e Observable são fundamentais em diversas situações no desenvolvimento de software. O Singleton é ideal quando precisamos garantir uma única instância de uma classe em toda a aplicação, enquanto o Observable é útil para notificar e gerenciar interações entre múltiplos objetos com base nas mudanças de estado.

Ao escolher entre esses padrões, considere as necessidades do seu projeto. Use o Singleton quando a unicidade de uma instância for crucial para a aplicação, e utilize o Observable quando o seu sistema precisar reagir a mudanças de estado ou eventos.

Top comments (0)