Factory Function em JavaScript

Escrito por

Hoje vou dar uma dica de JavaScript, mais especificamente como implementar o Patern Factory. Factory é bastante conhecido em Java, C# e outras linguagens com orientação a objeto. Nessas linguagens, retornamos uma instancia de uma classe, no JavaScript, poderíamos também, mas para ser mais funcional, podemos retornar um objeto de forma literal, ou seja, já em JavaScript. Vamos supor que eu tenha um Person Factory onde é passado o name:

1function personFactory(name) {
2 return {
3 name: name,
4
5 type: "person",
6 }
7}
8
9console.log(personFactory("Tulio"))
10
11console.log(personFactory("João"))

Quando executarmos o código, ele vai criar um objeto novo com o nome Tulio e outro com o nome João. Então uma das funcionalidades que temos para factory é criar objetos novos. Outra coisa bacana, mas bem especifico de linguagens funcionais e até da característica do JavaScript, é que temos uma closure, então acabamos conseguindo fazer um contador, por exemplo, com um count retornando uma arrow function..

1function personFactory(name) {
2 let count = 0
3
4 return {
5 count () => count++,
6 name: name,
7 type: 'person'
8 }
9}
10
11const tulio = personFactory('Tulio')
12
13const joao = personFactory('João')
14
15console.log(tulio)
16
17console.log(joao)

O primeiro count não é o mesmo que o de dentro, o de dentro é o que retornamos para a factory. Quando eu chamo o Person Factory passando o nome 'Tulio', ele vai criar um escopo novo que vai retornar somente esses dados, e junto com ele vai travar o contexto. O count vai ter o valor 0 para o objeto Tulio e depois para o objeto João, então se fizermos o seguinte:

1const tulio = personFactory("Tulio")
2
3const joao = personFactory("João")
4
5console.log(tulio.count())
6
7console.log(tulio.count())

Assim, conseguimos manter um estado para esse objeto porque temos uma closure sem nenhum this ou coisa desse sentido, com isso não temos problema nenhum de localização. Muita gente vai falar que não conseguimos o isolamento das variáveis, só que, na verdade, conseguimos sim utilizando closure. Vamos fazer um outro teste só que ao invés de chamar de count vou chamar de opa:

1function personFactory(name) {
2 let count = 0
3
4 return {
5 opa () => count++,
6 name: name,
7 type: 'person'
8 }
9}
10
11const tulio = personFactory('Tulio')
12
13const joao = personFactory('João')
14
15console.log(tulio.opa())
16
17console.log(tulio.opa())

Continua funcionando normalmente, porém se eu tentar fazer um console.log(tulio.count), que teoricamente seria o count de fora, ele apareceria undefined porque  está dentro da closure.

Quando retornado, ele cria uma nova interface publica para o objeto e as únicas que temos é o opa, name e type. Então podemos utilizar para gerar como se fosse uma classe de uma maneira mais funcional ou quando queremos retornar um objeto com várias propriedades que queremos deixar um ou dois dinâmicos apenas, construindo uma factory de um objeto que é um pouco mais complexo.

O factory em outras linguagens segue mais ou menos a mesma linha, a única diferença é que ele instancia realmente uma classe. Uma dica é que quando for pensar em programação funcional comece a restringir o uso do this, quanto mais longe estamos do this, mais próximo estamos da programação funcional.

Confira o video:

Curta o DevPleno no Facebook, inscreva-se no canal e não se esqueça de cadastrar seu e-mail para não perder as novidades. Abraço!

Evolua mais rápido

Junte-se a milhares de desenvolvedores no nosso time de alunos premium e alcance mais rápido o próximo nível da sua carreira.

Ver cursos Premium