4 maneiras de implementar o Factory Pattern em Javascript
Olá, meus amantes de bits favoritos .
Este artigo faz parte da Saga de Padrões que criei. Se você não leu outros artigos, pode navegar pelos links:
Para você que já sabe o que é Factory Pattern , continue navegando, tenho certeza que este artigo irá surpreendê-lo.
Para os outros…
Padrão de fábrica — um tipo de padrão de criação que geralmente descreve aspectos comuns das entidades criando uma classe base e permite que subclasses herdem seu comportamento e o alterem.
Quando o usamos?
Bem, geralmente usamos essa abordagem quando nossas entidades têm muito em comum e queremos criar uma classe base onde vamos manter tudo o que há em comum.
Isso é realmente útil para criar uma base de código DRY e clara.
Este artigo incluirá exemplos de Javascript e Typescript .
Fábrica Clássica
Fábrica mais icônica, descrita em todos os livros.
Existem algumas técnicas comuns de como podemos implementar o padrão de fábrica :
- Criamos um método em nossa classe base e esperamos que esse método não use algo que será alterado pelos filhos, assim como o método em si também não será alterado.
- Criamos uma propriedade em nossa classe base e esperamos que essa subclasse reatribua essa propriedade. Esta propriedade pode ser utilizada igualmente na classe base e na subclasse.
- Criamos um método que esperamos que seja implementado ou concluído em irmãos. Então, por exemplo, se queremos que os desenvolvedores implementem - definimos o método e o fazemos gerar um erro, é assim que os desenvolvedores serão forçados a implementá-lo.
Portanto, temos que ter a capacidade de visualizar nosso saldo, enviar e receber dinheiro e, obviamente, notificar nossa API sobre nossas alterações. A julgar por isso, essas coisas são em comum, a única diferença entre elas será o nome da moeda e, por exemplo, o gateway de pagamento.
Vamos ao código.
Exemplo de Javascript
Primeiramente vamos implementar nossa classe base .
Estou tentando cobrir o máximo de cenários possível aqui, então vamos percorrer o código e ver o que está acontecendo aqui. Aqui está uma lista que será alterada em irmãos:
- Linha 4 e Linha 6 — serão usadas em nossas subclasses, precisamos desses valores para manipular nossa URL na Linha 42 no
_updateAPImétodo. - Linha 32 — o método
_authenticateé criado para mostrar aos desenvolvedores que esperamos que esse método seja implementado em nossas subclasses, portanto, a menos que seja implementado, a linha 41 sempre gerará umImplement meerro. - Linha 36 — em
_updateAPIprimeiro verificamos se as variáveis que precisam ser definidas em nossos filhos estão definidas, se não estiverem definidas — lançamos um erro para destacar para o desenvolvedor que essas propriedades são necessárias. Então usamos_authenticateo que precisa ser definido em irmãos e usamos as variáveis que esperamos que sejam definidas em nossas subclasses.
E então nossa carteira de dólares :
Como você nos dois exemplos acima, você vê que estamos redefinindo as propriedades _currencye _gateway, bem como _authenticateo método de definição.
E agora podemos usar o em nossa aplicação:
const usdWallet = new USDWallet();
usdWallet.sendMoney(100);
usdWallet.receiveMoney(10);
A implementação do Typescript é muito próxima do que você vê no Javascript . Vamos começar com a criação dos nossos tipos :
Agora, implemente a classe base :
O que nos interessa aqui é como mostramos aos desenvolvedores o que esperamos fazer com os métodos, por exemplo:
publiceprotectedmétodos podem ser redefinidos em irmãosprivatemétodos não podem ser redefinidos em subclasses- Além disso, dê uma olhada em como estamos manipulando com
nevero tipo no Typescript. Nossoauthenticatemétodo retornavoid | never, mas vamos modificar isso em filhos, para retornar apenasvoid
E USDWalletclasse:
Como você pode ver, redefinimos as propriedades, o método e também podemos modificar os tipos de retorno, neste caso, authenticateapenas o retorno do método void.
Prós
- Implementação icônica
- Igualmente legível e eficiente
- Pode ser usado com JavaScript e Typescript
- Requer código adicional, para validar que tudo foi feito corretamente
Typescript nos permite usar uma abordagem maravilhosa com abstractclasse. Como esse recurso está disponível apenas em Typescript , você não encontrará um exemplo de JavaScript aqui.
Então, o que é uma abstractclasse em TypeScript ? Uma classe especial que pode ser usada apenas para herança e não pode ser usada para criar uma nova instância. Permite implementar métodos e propriedades, mas também permite criar um esqueleto de método ou propriedade, com abstractpalavra-chave dentro de uma classe.
Uma vez que isso está resolvido, vamos para a implementação:
Como sempre, vamos percorrer o código:
- A primeira coisa que você notará é a Linha 3 , um exemplo de
abstractuso de classe - A seguir, nas linhas 4, 6 e 8, você pode ver como definimos um esqueleto dos irmãos. Basicamente, dizemos ao Typescript como esperamos que essas propriedades pareçam, e o Typescript forçará os desenvolvedores a implementar ou atribuir essas propriedades em irmãos.
Prós
- Tenha todos os benefícios do Classic Factory
- Requer menos código para implementar
- Requer conhecimento adicional do Typescript
Mais uma vez vamos utilizar o recurso que está presente apenas no Typescript . Chama-se implements.
Então o que é implements?
É uma ferramenta em Typescript que nos permite validar se o objeto tem a mesma estrutura que descrevemos.
Em primeiro lugar, precisamos implementar um interfaceque irá descrever um esqueleto de nossas classes futuras.
Como estamos mudando nossa abordagem, também precisamos retrabalhar nossa lógica.
Como você pode ver, nossa interface é um pouco mais fina do que nossa classe base era antes. Não precisamos mais de algumas das propriedades que descrevemos anteriormente, por exemplo:
- Não precisamos
currencyegatewaymais nada, pois vamos descrevê-lo manualmente - Não precisamos mais
authenticateda função porque vamos implementá-la manualmente para cada classe
E a nossa carteira Euro :
Agora vamos resumir tudo.
Como você vê, precisamos descrever cada método manualmente, o que basicamente leva a muita duplicação de código. Mas, do lado oposto desse argumento, você pode descobrir que os métodos são diferentes e não precisa seguir as regras da superclasse. E o Typescript ajudará você a validar se a classe possui a estrutura necessária.
Prós
- Abordagem flexível
- É útil quando você deseja manter uma única interface de acesso para chamar métodos de instância
- Requer escrever mais código ou incluir outras abordagens para tornar sua base de código DRY
- Você não pode herdar métodos estáticos, pois
interfacenão permite que você tenha um
Em algum momento você se perguntará: é possível adotar uma abordagem OOP e usá-la na programação funcional?
Então, o legal do JavaScript é que ele é uma linguagem de programação multiparadigma e permite o uso de abordagens OOP e funcionais.
E há muitos casos em que OOP não é adequado apenas para o que estamos fazendo, então a pergunta é: Existe uma maneira de aplicar o padrão Factory na programação funcional?
Sim existe.
Então vamos fazer outro exemplo:
Temos um aplicativo que se comunica com troca de criptografia e precisamos receber uma atualização por meio de WebSockets . Precisamos nos inscrever em diferentes canais, por exemplo, um canal será o livro de pedidos e o segundo serão os tickers . Mas precisamos ter a mesma interface para assinar e cancelar .
Exemplo de JavaScript
Como você pode ver aqui, criamos uma fábrica de funções que gera duas funções que podemos usar. Lembre-se de que retornamos tuple, caso desejemos renomear results.
event— será o nome do canal WebSockets , no nosso caso, pode serorderbookoutickeronEvent— será um manipulador quando recebermos atualização de soquetes
E é assim que se usa:
const [orderbookSubscribe, orderbookUnsubscribe] = wsCommunicationFactory(
'orderbook',
(payload: object) => updateOrderbookUI(payload),
);
const [tickerSubscribe, tickerUnsubscribe] = wsCommunicationFactory(
'ticker',
(payload: object) => updateTickerUI(payload),
);
Prós
- A única forma de implementar um padrão Factory na programação funcional
- Útil quando seu projeto é totalmente padronizado e possui uma estrutura única
- Requer um pouco de experiência de um desenvolvedor
- Vários argumentos e configurações tornarão essa abordagem insuportável
- Funções internas complexas dificultarão a leitura e o suporte
- Link para o repositório
Não se esqueça de me seguir para mais!
Sua parte. ABRAÇOS E BEIJOS





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)