DEV Community

Lucas Pereira de Souza
Lucas Pereira de Souza

Posted on

1

Entendendo e Implementando Design Patterns em TypeScript

Image description
Design Patterns são soluções generalistas para problemas recorrentes no desenvolvimento de software. Esses padrões ajudam a estruturar o código de forma organizada, facilitando a manutenção, a reutilização e a escalabilidade do sistema. Em TypeScript, um superconjunto de JavaScript, os Design Patterns podem ser implementados de forma ainda mais eficiente devido à forte tipagem e recursos de orientação a objetos.

Neste post, exploraremos três categorias principais de Design Patterns (Criacionais, Estruturais e Comportamentais) e como implementá-los em TypeScript.


1. Padrões Criacionais

Os padrões criacionais lidam com a criação de objetos, ajudando a encapsular o processo de instância e a promover a reutilização do código.

Exemplo: Singleton

O Singleton garante que uma classe tenha apenas uma única instância durante todo o ciclo de vida da aplicação.

class Singleton {
    private static instance: Singleton;

    private constructor() {}

    static getInstance(): Singleton {
        if (!Singleton.instance) {
            Singleton.instance = new Singleton();
        }
        return Singleton.instance;
    }

    someMethod() {
        console.log("Método do Singleton");
    }
}

const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();

console.log(instance1 === instance2); // true
Enter fullscreen mode Exit fullscreen mode

No exemplo acima, o método getInstance() garante que apenas uma instância da classe Singleton seja criada.

2. Padrões Estruturais

Os padrões estruturais tratam da composição de classes e objetos, garantindo que grandes estruturas de código possam ser construídas a partir de peças menores e mais simples.

Exemplo: Adapter

O padrão Adapter permite que duas interfaces incompatíveis trabalhem juntas. Isso é útil quando você quer utilizar uma classe que tem uma interface diferente da que o seu código espera.

// Interface antiga
class OldAPI {
    oldRequest() {
        return "Dados da API antiga";
    }
}

// Interface nova
class NewAPI {
    newRequest() {
        return "Dados da API nova";
    }
}

// Adapter que adapta a interface antiga para a nova
class APIAdapter {
    private oldAPI: OldAPI;

    constructor(oldAPI: OldAPI) {
        this.oldAPI = oldAPI;
    }

    newRequest() {
        return this.oldAPI.oldRequest();
    }
}

const oldAPI = new OldAPI();
const adapter = new APIAdapter(oldAPI);

console.log(adapter.newRequest()); // "Dados da API antiga"
Enter fullscreen mode Exit fullscreen mode

Nesse exemplo, o Adapter (APIAdapter) permite que a classe OldAPI seja utilizada com a interface esperada pela NewAPI.

3. Padrões Comportamentais

Os padrões comportamentais lidam com a interação e comunicação entre objetos, promovendo a flexibilidade e a desacoplagem no código.

Exemplo: Observer

O padrão Observer define uma dependência um-para-muitos entre objetos de forma que, quando um objeto muda de estado, todos os seus dependentes são notificados e atualizados automaticamente.

interface Observer {
    update(data: any): void;
}

class Subject {
    private observers: Observer[] = [];

    addObserver(observer: Observer) {
        this.observers.push(observer);
    }

    removeObserver(observer: Observer) {
        this.observers = this.observers.filter(obs => obs !== observer);
    }

    notifyObservers(data: any) {
        this.observers.forEach(observer => observer.update(data));
    }
}

class ConcreteObserver implements Observer {
    update(data: any) {
        console.log("Observer atualizado com dados:", data);
    }
}

const subject = new Subject();
const observer1 = new ConcreteObserver();
const observer2 = new ConcreteObserver();

subject.addObserver(observer1);
subject.addObserver(observer2);

subject.notifyObservers("Alguma informação importante");
// Ambos observers recebem a atualização
Enter fullscreen mode Exit fullscreen mode

No exemplo acima, o padrão Observer permite que vários objetos observem e reajam às mudanças de estado de um objeto sujeito (Subject).


Conclusão

Os Design Patterns são ferramentas poderosas para a construção de código robusto e escalável. TypeScript, com suas características de tipagem estática e orientação a objetos, é um ambiente excelente para implementar esses padrões, proporcionando maior segurança e produtividade no desenvolvimento.

Ao utilizar padrões criacionais, estruturais e comportamentais, você estará adotando práticas que melhoram a legibilidade e manutenção do código, garantindo soluções eficazes para problemas comuns de desenvolvimento.


Espero que este post tenha ajudado a entender como aplicar Design Patterns em TypeScript. Experimente essas implementações nos seus projetos e veja como elas podem melhorar a qualidade do seu código!

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay