{"id":57135,"date":"2023-02-14T05:23:29","date_gmt":"2023-02-14T08:23:29","guid":{"rendered":"https:\/\/kinsta.com\/pt\/?p=57135&#038;preview=true&#038;preview_id=57135"},"modified":"2023-08-22T03:35:35","modified_gmt":"2023-08-22T06:35:35","slug":"padroes-de-design-javascript","status":"publish","type":"post","link":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/","title":{"rendered":"Um Guia Extensivo de Padr\u00f5es de Design JavaScript"},"content":{"rendered":"<p>Ao construir aplicativos <a href=\"https:\/\/kinsta.com\/pt\/blog\/o-que-e-javascript\/\">JavaScript<\/a>, voc\u00ea pode encontrar cen\u00e1rios onde voc\u00ea precisa construir objetos de uma certa forma predefinida ou reutilizar uma classe comum, modificando ou adaptando para v\u00e1rios casos de uso.<\/p>\n<p>\u00c9 claro que n\u00e3o \u00e9 conveniente resolver esses problemas repetidamente.<\/p>\n<p>\u00c9 aqui que os padr\u00f5es de design JavaScript v\u00eam em seu socorro.<\/p>\n<p>Os padr\u00f5es de design JavaScript fornecem a voc\u00ea uma maneira estruturada e repet\u00edvel de resolver problemas que ocorrem comumente no desenvolvimento do JavaScript.<\/p>\n<p>Neste guia, vamos dar uma olhada no que s\u00e3o padr\u00f5es de design JavaScript e como us\u00e1-los em seus aplicativos JavaScript.<div><\/div><kinsta-auto-toc heading=\"Table of Contents\" exclude=\"last\" list-style=\"arrow\" selector=\"h2\" count-number=\"-1\"><\/kinsta-auto-toc><\/p>\n<h2>O que \u00e9 um padr\u00e3o de design JavaScript?<\/h2>\n<p>Os padr\u00f5es de design JavaScript s\u00e3o solu\u00e7\u00f5es de template repet\u00edveis para problemas frequentes no desenvolvimento de aplicativos JavaScript.<\/p>\n<p>A ideia \u00e9 simples: Programadores em todo o mundo, desde o in\u00edcio do desenvolvimento, t\u00eam enfrentado conjuntos de problemas recorrentes ao <a href=\"https:\/\/kinsta.com\/pt\/blog\/desenvolvedor-de-aplicativos\/\">desenvolver aplicativos<\/a>. Ao longo do tempo, alguns desenvolvedores escolheram documentar formas testadas e comprovadas de lidar com esses problemas para que outros pudessem se referir \u00e0s solu\u00e7\u00f5es com facilidade.<\/p>\n<p>Conforme mais e mais desenvolvedores escolhiam usar essas solu\u00e7\u00f5es e reconheciam sua efici\u00eancia na solu\u00e7\u00e3o de seus problemas, eles se tornaram aceitos como uma forma padr\u00e3o de solu\u00e7\u00e3o de problemas e receberam o nome de &#8220;padr\u00f5es de design&#8221;<\/p>\n<p>\u00c0 medida que a import\u00e2ncia dos padr\u00f5es de design foi melhor compreendida, eles foram aprimorados e padronizados. A maioria dos padr\u00f5es de design modernos possui uma estrutura definida, s\u00e3o organizados em v\u00e1rias categorias e s\u00e3o ensinados em cursos relacionados \u00e0 ci\u00eancia da computa\u00e7\u00e3o como t\u00f3picos independentes.<\/p>\n<h2>Tipos de padr\u00f5es de design JavaScript<\/h2>\n<p>Aqui est\u00e3o algumas das mais populares classifica\u00e7\u00f5es de padr\u00f5es de design JavaScript.<\/p>\n<h3>Criativo<\/h3>\n<p>Padr\u00f5es de design criativos s\u00e3o aqueles que ajudam a resolver problemas em torno da cria\u00e7\u00e3o e gerenciamento de novas inst\u00e2ncias de objetos JavaScript. Pode ser t\u00e3o simples quanto limitar uma classe a ter apenas um objeto ou t\u00e3o complexo quanto definir um m\u00e9todo intrincado de sele\u00e7\u00e3o manual e adicionar cada recurso em um objeto JavaScript.<\/p>\n<p>Alguns exemplos de padr\u00f5es de design criativo incluem Singleton, Factory, Abstract Factory, e Builder, entre outros.<\/p>\n<h3>Estrutural<\/h3>\n<p>Os padr\u00f5es de projeto estrutural s\u00e3o aqueles que ajudam a resolver problemas em torno do gerenciamento da estrutura (ou esquema) dos objetos JavaScript. Estes problemas podem incluir a cria\u00e7\u00e3o de uma rela\u00e7\u00e3o entre dois objetos diferentes ou a abstra\u00e7\u00e3o de algumas caracter\u00edsticas de um objeto para usu\u00e1rios espec\u00edficos.<\/p>\n<p>Alguns exemplos de padr\u00f5es de projeto estrutural incluem Adapter, Bridge, Composite, e Facade.<\/p>\n<h3>Comportamental<\/h3>\n<p>Os padr\u00f5es de design comportamentais s\u00e3o aqueles que ajudam a resolver problemas relacionados a como o controle (e responsabilidade) \u00e9 passado entre v\u00e1rios objetos. Esses problemas podem envolver o controle de acesso a uma lista encadeada ou o estabelecimento de uma entidade \u00fanica que possa controlar o acesso a v\u00e1rios tipos de objetos.<\/p>\n<p>Alguns exemplos de padr\u00f5es de design comportamentais incluem Command, Iterator, Memento, e Observer.<\/p>\n<h3>Concorr\u00eancia<\/h3>\n<p>Os padr\u00f5es de design de concorr\u00eancia s\u00e3o aqueles que ajudam a resolver problemas relacionados \u00e0 execu\u00e7\u00e3o simult\u00e2nea de v\u00e1rias threads e tarefas. Esses problemas podem envolver a manuten\u00e7\u00e3o de um objeto ativo entre v\u00e1rios objetos dispon\u00edveis ou o gerenciamento de v\u00e1rios eventos fornecidos a um sistema, processando a entrada recebida em partes separadas.<\/p>\n<p>Alguns exemplos de padr\u00f5es de projeto de concorr\u00eancia incluem objeto ativo, nuclear react e scheduler.<\/p>\n<h3>Arquitetura<\/h3>\n<p>Padr\u00f5es de design de arquitetura s\u00e3o aqueles que ajudam a resolver problemas relacionados ao <a href=\"https:\/\/kinsta.com\/pt\/blog\/arquitetura-aplicativos-web\/\">design de software<\/a> de maneira ampla. Eles est\u00e3o geralmente relacionados a como projetar seu sistema e garantir alta disponibilidade, mitigar riscos e <a href=\"https:\/\/kinsta.com\/pt\/blog\/monitoramento-desempenho-aplicativos\/\">evitar gargalos de desempenho<\/a>.<\/p>\n<p>Dois exemplos de padr\u00f5es de design de arquitetura s\u00e3o o MVC (Model-View-Controller) e o MVVM (Model-View-ViewModel).<\/p>\n<h2>Elementos de padr\u00e3o de design<\/h2>\n<p>Quase todos os padr\u00f5es de design podem ser decompostos em um conjunto de quatro componentes importantes. Eles s\u00e3o:<\/p>\n<ul>\n<li><strong>Pattern name<\/strong>: Este \u00e9 usado para identificar um padr\u00e3o de design enquanto se comunica com outros usu\u00e1rios. Exemplos incluem &#8220;singleton,&#8221; &#8220;prot\u00f3tipo,&#8221; e muito mais.<\/li>\n<li><strong>Problem<\/strong>: Isso descreve o objetivo do padr\u00e3o de design. \u00c9 uma pequena descri\u00e7\u00e3o do problema que o padr\u00e3o de desenho est\u00e1 tentando resolver. Pode at\u00e9 incluir um exemplo de cen\u00e1rio para explicar melhor o problema. Ele tamb\u00e9m pode conter uma lista de condi\u00e7\u00f5es a serem cumpridas para que um padr\u00e3o de design resolva completamente o problema subjacente.<\/li>\n<li><strong>Solution<\/strong>: Esta \u00e9 a solu\u00e7\u00e3o para o problema em quest\u00e3o, composta de elementos como classes, m\u00e9todos, interfaces, etc. \u00c9 onde est\u00e1 o grosso de um padr\u00e3o de design &#8211; ele envolve relacionamentos, responsabilidades e colaboradores de v\u00e1rios elementos que s\u00e3o claramente definidos.<\/li>\n<li><strong>Results<\/strong>: Esta \u00e9 uma an\u00e1lise de qu\u00e3o bem o padr\u00e3o conseguiu resolver o problema. Coisas como espa\u00e7o e uso de tempo s\u00e3o discutidas, juntamente com abordagens alternativas para resolver o mesmo problema.<\/li>\n<\/ul>\n<p>Se voc\u00ea est\u00e1 procurando aprender mais sobre padr\u00f5es de design e seu in\u00edcio, MSU tem algum <a href=\"https:\/\/www.cse.msu.edu\/~cse870\/Lectures\/SS2005\/08-design-patterns.ppt\">material de estudo sucinto<\/a> que voc\u00ea pode consultar.<\/p>\n<h2>Por que voc\u00ea deve usar padr\u00f5es de design?<\/h2>\n<p>Existem m\u00faltiplas raz\u00f5es pelas quais voc\u00ea gostaria de usar padr\u00f5es de design:<\/p>\n<ul>\n<li><strong>Eles s\u00e3o experimentados e testados<\/strong>: Com um padr\u00e3o de design, voc\u00ea tem uma solu\u00e7\u00e3o testada e comprovada para o seu problema (desde que o padr\u00e3o de design se ajuste \u00e0 descri\u00e7\u00e3o do seu problema). Voc\u00ea n\u00e3o precisa perder tempo procurando por solu\u00e7\u00f5es alternativas, e voc\u00ea pode ter certeza de que voc\u00ea tem uma solu\u00e7\u00e3o que cuida da otimiza\u00e7\u00e3o b\u00e1sica de desempenho para voc\u00ea.<\/li>\n<li><strong>Eles s\u00e3o f\u00e1ceis de entender<\/strong>: Os padr\u00f5es de design s\u00e3o projetados para serem pequenos, simples e f\u00e1ceis de entender. Voc\u00ea n\u00e3o precisa ser um programador especializado trabalhando em uma ind\u00fastria espec\u00edfica h\u00e1 d\u00e9cadas para entender qual padr\u00e3o de design usar. Eles s\u00e3o propositalmente gen\u00e9ricos (n\u00e3o limitados a nenhuma linguagem de programa\u00e7\u00e3o espec\u00edfica) e podem ser entendidos por qualquer pessoa que tenha habilidades suficientes de resolu\u00e7\u00e3o de problemas. Isso tamb\u00e9m ajuda quando h\u00e1 uma mudan\u00e7a de equipe t\u00e9cnica: um c\u00f3digo que depende de um padr\u00e3o de design \u00e9 mais f\u00e1cil de entender para qualquer novo desenvolvedor de software.<\/li>\n<\/ul>\n<ul>\n<li><strong>Eles s\u00e3o simples de implementar<\/strong>:\u00a0A maioria dos padr\u00f5es de design s\u00e3o muito simples, como voc\u00ea ver\u00e1 mais adiante em nosso artigo. Voc\u00ea n\u00e3o precisa conhecer m\u00faltiplos <a href=\"https:\/\/kinsta.com\/pt\/blog\/programacao-orientada-objetos-python\/\">conceitos de programa\u00e7\u00e3o<\/a> para implement\u00e1-los em seu c\u00f3digo.<\/li>\n<\/ul>\n<ul>\n<li><strong>Eles prop\u00f5em uma arquitetura de c\u00f3digo facilmente reutiliz\u00e1vel<\/strong>: A reutiliza\u00e7\u00e3o e a organiza\u00e7\u00e3o do <a href=\"https:\/\/kinsta.com\/pt\/blog\/melhores-praticas-html\/\">c\u00f3digo s\u00e3o fortemente encorajadas em toda a ind\u00fastria de tecnologia<\/a>, e os padr\u00f5es de design podem ajud\u00e1-lo a alcan\u00e7ar isso. Como esses padr\u00f5es s\u00e3o uma maneira padr\u00e3o de resolver problemas, seus designers se esfor\u00e7aram para garantir que a arquitetura do aplicativo seja reutiliz\u00e1vel, flex\u00edvel e compat\u00edvel com a maioria das formas de escrita de c\u00f3digo.<\/li>\n<\/ul>\n<ul>\n<li><strong>Eles economizam tempo e tamanho do aplicativo<\/strong>: Um dos maiores benef\u00edcios de contar com um conjunto padr\u00e3o de solu\u00e7\u00f5es \u00e9 que eles ajudar\u00e3o voc\u00ea a economizar tempo ao implement\u00e1-los. Existe uma boa chance de que toda \u00e0 sua equipe de desenvolvimento conhe\u00e7a bem os padr\u00f5es de design, facilitando o <a href=\"https:\/\/kinsta.com\/pt\/blog\/microsoft-teams-vs-slack\/\">planejamento, a comunica\u00e7\u00e3o e a colabora\u00e7\u00e3o<\/a> durante a implementa\u00e7\u00e3o. Solu\u00e7\u00f5es testadas e comprovadas significam que h\u00e1 uma boa chance de voc\u00ea n\u00e3o acabar vazando recursos ou fazendo um desvio ao construir algum recurso, economizando tempo e espa\u00e7o. Al\u00e9m disso, a maioria das <a href=\"https:\/\/kinsta.com\/pt\/blog\/melhor-linguagem-de-programacao\/\">linguagens de programa\u00e7\u00e3o<\/a> fornece bibliotecas de modelos padr\u00e3o que j\u00e1 implementam alguns padr\u00f5es de design comuns, como Iterator e Observer.<\/li>\n<\/ul>\n<h2>Os 20 principais padr\u00f5es de design JavaScript para dominar<\/h2>\n<p>Agora que voc\u00ea entende do que um padr\u00e3o de design \u00e9 composto e por que voc\u00ea precisa deles, vamos mergulhar mais fundo em como alguns dos padr\u00f5es de design JavaScript mais comumente utilizados podem ser implementados em um <a href=\"https:\/\/kinsta.com\/pt\/blog\/aplicativos-node-js\/\">aplicativo JavaScript<\/a>.<\/p>\n<h3>Criativo<\/h3>\n<p>Vamos come\u00e7ar a discuss\u00e3o com alguns padr\u00f5es fundamentais e f\u00e1ceis de aprender, de design criativo.<\/p>\n<h4>1. Singleton<\/h4>\n<p>O padr\u00e3o Singleton \u00e9 um dos padr\u00f5es de design mais comumente usados em toda a ind\u00fastria de desenvolvimento de software. O problema que ele visa resolver \u00e9 manter apenas uma \u00fanica inst\u00e2ncia de uma classe. Isso pode ser \u00fatil quando se instanciam objetos que consomem muitos recursos, tais como manipuladores de banco de dados.<\/p>\n<p>Aqui est\u00e1 como voc\u00ea pode implement\u00e1-lo no JavaScript:<\/p>\n<pre><code class=\"language-js\">function SingletonFoo() {\n\n   let fooInstance = null;\n\n   \/\/ For our reference, let's create a counter that will track the number of active instances\n   let count = 0;\n\n   function printCount() {\n       console.log(\"Number of instances: \" + count);\n   }\n\n   function init() {\n       \/\/ For our reference, we'll increase the count by one whenever init() is called\n       count++;\n\n       \/\/ Do the initialization of the resource-intensive object here and return it\n       return {}\n   }\n\n   function createInstance() {\n       if (fooInstance == null) {\n           fooInstance = init();\n       }\n       return fooInstance;\n   }\n\n   function closeInstance() {\n       count--;\n       fooInstance = null;\n   }\n\n   return {\n       initialize: createInstance,\n       close: closeInstance,\n       printCount: printCount\n   }\n}\n\nlet foo = SingletonFoo();\n\nfoo.printCount() \/\/ Prints 0\nfoo.initialize()\nfoo.printCount() \/\/ Prints 1\nfoo.initialize()\nfoo.printCount() \/\/ Still prints 1\nfoo.initialize()\nfoo.printCount() \/\/ Still 1\nfoo.close()\nfoo.printCount() \/\/ Prints 0<\/code><\/pre>\n<p>Embora o padr\u00e3o Singleton cumpra bem seu prop\u00f3sito, \u00e9 conhecido por dificultar a depura\u00e7\u00e3o, pois oculta as depend\u00eancias e controla o acesso \u00e0 inicializa\u00e7\u00e3o ou destrui\u00e7\u00e3o das inst\u00e2ncias de uma classe.<\/p>\n<h4>2. Factory<\/h4>\n<p>O Factory method tamb\u00e9m \u00e9 um dos padr\u00f5es de design mais populares. O problema que o Factory method visa resolver \u00e9 a cria\u00e7\u00e3o de objetos sem usar o construtor convencional. Em vez disso, ele recebe a configura\u00e7\u00e3o (ou descri\u00e7\u00e3o) do objeto desejado e retorna o objeto rec\u00e9m-criado.<\/p>\n<p>Aqui est\u00e1 como voc\u00ea pode implement\u00e1-lo em JavaScript:<\/p>\n<pre><code class=\"language-js\">function Factory() {\n   this.createDog = function (breed) {\n       let dog;\n\n       if (breed === \"labrador\") {\n           dog = new Labrador();\n       } else if (breed === \"bulldog\") {\n           dog = new Bulldog();\n       } else if (breed === \"golden retriever\") {\n           dog = new GoldenRetriever();\n       } else if (breed === \"german shepherd\") {\n           dog = new GermanShepherd();\n       }\n\n       dog.breed = breed;\n       dog.printInfo = function () {\n           console.log(\"nnBreed: \" + dog.breed + \"nShedding Level (out of 5): \" + dog.sheddingLevel + \"nCoat Length: \" + dog.coatLength + \"nCoat Type: \" + dog.coatType)\n       }\n\n       return dog;\n   }\n}\n\nfunction Labrador() {\n   this.sheddingLevel = 4\n   this.coatLength = \"short\"\n   this.coatType = \"double\"\n}\n\nfunction Bulldog() {\n   this.sheddingLevel = 3\n   this.coatLength = \"short\"\n   this.coatType = \"smooth\"\n}\n\nfunction GoldenRetriever() {\n   this.sheddingLevel = 4\n   this.coatLength = \"medium\"\n   this.coatType = \"double\"\n}\n\nfunction GermanShepherd() {\n   this.sheddingLevel = 4\n   this.coatLength = \"medium\"\n   this.coatType = \"double\"\n}\n\nfunction run() {\n\n   let dogs = [];\n   let factory = new Factory();\n\n   dogs.push(factory.createDog(\"labrador\"));\n   dogs.push(factory.createDog(\"bulldog\"));\n   dogs.push(factory.createDog(\"golden retriever\"));\n   dogs.push(factory.createDog(\"german shepherd\"));\n\n   for (var i = 0, len = dogs.length; i &lt; len; i++) {\n       dogs[i].printInfo();\n   }\n}\n\nrun()\n\n\/**\nOutput:\n\nBreed: labrador\nShedding Level (out of 5): 4\nCoat Length: short\nCoat Type: double\n\n\nBreed: bulldog\nShedding Level (out of 5): 3\nCoat Length: short\nCoat Type: smooth\n\n\nBreed: golden retriever\nShedding Level (out of 5): 4\nCoat Length: medium\nCoat Type: double\n\n\nBreed: german shepherd\nShedding Level (out of 5): 4\nCoat Length: medium\nCoat Type: double\n*\/<\/code><\/pre>\n<p>O padr\u00e3o de design Factory controla como os objetos ser\u00e3o criados e fornece uma maneira r\u00e1pida de criar novos objetos, al\u00e9m de uma interface uniforme que define as propriedades que seus objetos ter\u00e3o. Voc\u00ea pode adicionar quantas ra\u00e7as de cachorro quiser, mas desde que os m\u00e9todos e propriedades expostos pelos tipos de ra\u00e7a permane\u00e7am os mesmos, eles funcionar\u00e3o perfeitamente.<\/p>\n<p>No entanto, observe que o padr\u00e3o Factory pode levar a um grande n\u00famero de classes, o que pode ser dif\u00edcil de gerenciar.<\/p>\n<h4>3. Factoryde Resumos<\/h4>\n<p>O padr\u00e3o de design Factory controla como os objetos ser\u00e3o criados e fornece uma maneira r\u00e1pida de criar novos objetos, al\u00e9m de uma interface uniforme que define as propriedades que seus objetos ter\u00e3o. Voc\u00ea pode adicionar quantas ra\u00e7as de cachorro quiser, desde que os m\u00e9todos e propriedades expostos pelos tipos de ra\u00e7a permane\u00e7am os mesmos, eles funcionar\u00e3o perfeitamente.<\/p>\n<p>No entanto, \u00e9 importante observar que o padr\u00e3o Factory pode resultar em um grande n\u00famero de classes, o que pode ser dif\u00edcil de gerenciar.<\/p>\n<pre><code class=\"language-js\">\/\/ A factory to create dogs\nfunction DogFactory() {\n   \/\/ Notice that the create function is now createPet instead of createDog, since we need\n   \/\/ it to be uniform across the other factories that will be used with this\n   this.createPet = function (breed) {\n       let dog;\n\n       if (breed === \"labrador\") {\n           dog = new Labrador();\n       } else if (breed === \"pug\") {\n           dog = new Pug();\n       }\n\n       dog.breed = breed;\n       dog.printInfo = function () {\n           console.log(\"nnType: \" + dog.type + \"nBreed: \" + dog.breed + \"nSize: \" + dog.size)\n       }\n\n       return dog;\n   }\n}\n\n\/\/ A factory to create cats\nfunction CatFactory() {\n   this.createPet = function (breed) {\n       let cat;\n\n       if (breed === \"ragdoll\") {\n           cat = new Ragdoll();\n       } else if (breed === \"singapura\") {\n           cat = new Singapura();\n       }\n\n       cat.breed = breed;\n       cat.printInfo = function () {\n           console.log(\"nnType: \" + cat.type + \"nBreed: \" + cat.breed + \"nSize: \" + cat.size)\n       }\n\n       return cat;\n   }\n}\n\n\/\/ Dog and cat breed definitions\nfunction Labrador() {\n   this.type = \"dog\"\n   this.size = \"large\"\n}\n\nfunction Pug() {\n   this.type = \"dog\"\n   this.size = \"small\"\n}\n\nfunction Ragdoll() {\n   this.type = \"cat\"\n   this.size = \"large\"\n}\n\nfunction Singapura() {\n   this.type = \"cat\"\n   this.size = \"small\"\n}\n\nfunction run() {\n\n   let pets = [];\n\n   \/\/ Initialize the two factories\n   let catFactory = new CatFactory();\n   let dogFactory = new DogFactory();\n\n   \/\/ Create a common petFactory that can produce both cats and dogs\n   \/\/ Set it to produce dogs first\n   let petFactory = dogFactory;\n\n   pets.push(petFactory.createPet(\"labrador\"));\n   pets.push(petFactory.createPet(\"pug\"));\n\n   \/\/ Set the petFactory to produce cats\n   petFactory = catFactory;\n\n   pets.push(petFactory.createPet(\"ragdoll\"));\n   pets.push(petFactory.createPet(\"singapura\"));\n\n   for (var i = 0, len = pets.length; i &lt; len; i++) {\n       pets[i].printInfo();\n   }\n}\n\nrun()\n\n\/**\nOutput:\n\nType: dog\nBreed: labrador\nSize: large\n\n\nType: dog\nBreed: pug\nSize: small\n\n\nType: cat\nBreed: ragdoll\nSize: large\n\n\nType: cat\nBreed: singapura\nSize: small\n\n*\/<\/code><\/pre>\n<p>O padr\u00e3o Abstract Factory facilita a troca de f\u00e1bricas concretas de forma f\u00e1cil e ajuda a promover a uniformidade entre as f\u00e1bricas e os produtos criados. No entanto, pode se tornar dif\u00edcil introduzir novos tipos de produtos, pois seria necess\u00e1rio fazer altera\u00e7\u00f5es em v\u00e1rias classes para acomodar novos m\u00e9todos\/propriedades.<\/p>\n<h4>4. Builder<\/h4>\n<p>O padr\u00e3o Builder \u00e9 um dos padr\u00f5es de design de cria\u00e7\u00e3o mais complexos e flex\u00edveis em JavaScript. Ele permite que voc\u00ea construa cada recurso do seu produto passo a passo, fornecendo controle total sobre como seu objeto \u00e9 constru\u00eddo, ao mesmo tempo, em que abstrai os detalhes internos.<\/p>\n<p>No exemplo abaixo, voc\u00ea ver\u00e1 o padr\u00e3o de design Builder em a\u00e7\u00e3o, juntamente com o Diretor para ajudar a fazer Pizzas!<\/p>\n<pre><code class=\"language-js\">\/\/ Here's the PizzaBuilder (you can also call it the chef)\nfunction PizzaBuilder() {\n   let base\n   let sauce\n   let cheese\n   let toppings = []\n\n   \/\/ The definition of pizza is hidden from the customers\n   function Pizza(base, sauce, cheese, toppings) {\n       this.base = base\n       this.sauce = sauce\n       this.cheese = cheese\n       this.toppings = toppings\n\n       this.printInfo = function() {\n           console.log(\"This pizza has \" + this.base + \" base with \" + this.sauce + \" sauce \"\n           + (this.cheese !== undefined ? \"with cheese. \" : \"without cheese. \")\n           + (this.toppings.length !== 0 ? \"It has the following toppings: \" + toppings.toString() : \"\"))\n       }\n   }\n\n   \/\/ You can request the PizzaBuilder (\/chef) to perform any of the following actions on your pizza\n   return {\n       addFlatbreadBase: function() {\n           base = \"flatbread\"\n           return this;\n       },\n       addTomatoSauce: function() {\n           sauce = \"tomato\"\n           return this;\n       },\n       addAlfredoSauce: function() {\n           sauce = \"alfredo\"\n           return this;\n       },\n       addCheese: function() {\n           cheese = \"parmesan\"\n           return this;\n       },\n       addOlives: function() {\n           toppings.push(\"olives\")\n           return this\n       },\n       addJalapeno: function() {\n           toppings.push(\"jalapeno\")\n           return this\n       },\n       cook: function() {\n           if (base === null){\n               console.log(\"Can't make a pizza without a base\")\n               return\n           }\n           return new Pizza(base, sauce, cheese, toppings)\n       }\n   }\n\n}\n\n\/\/ This is the Director for the PizzaBuilder, aka the PizzaShop.\n\/\/ It contains a list of preset steps that can be used to prepare common pizzas (aka recipes!)\nfunction PizzaShop() {\n   return {\n       makePizzaMargherita: function() {\n           pizzaBuilder = new PizzaBuilder()\n           pizzaMargherita = pizzaBuilder.addFlatbreadBase().addTomatoSauce().addCheese().addOlives().cook()\n           return pizzaMargherita\n       },\n       makePizzaAlfredo: function() {\n           pizzaBuilder = new PizzaBuilder()\n           pizzaAlfredo = pizzaBuilder.addFlatbreadBase().addAlfredoSauce().addCheese().addJalapeno().cook()\n           return pizzaAlfredo\n       },\n       makePizzaMarinara: function() {\n           pizzaBuilder = new PizzaBuilder()\n           pizzaMarinara = pizzaBuilder.addFlatbreadBase().addTomatoSauce().addOlives().cook()\n           return pizzaMarinara\n       }\n   }\n}\n\n\/\/ Here's where the customer can request pizzas from\nfunction run() {\n\n   let pizzaShop = new PizzaShop()\n\n   \/\/ You can ask for one of the popular pizza recipes...\n   let pizzaMargherita = pizzaShop.makePizzaMargherita()\n   pizzaMargherita.printInfo()\n   \/\/ Output: This pizza has flatbread base with tomato sauce with cheese. It has the following toppings: olives\n\n   let pizzaAlfredo = pizzaShop.makePizzaAlfredo()\n   pizzaAlfredo.printInfo()\n   \/\/ Output: This pizza has flatbread base with alfredo sauce with cheese. It has the following toppings: jalapeno\n\n   let pizzaMarinara = pizzaShop.makePizzaMarinara()\n   pizzaMarinara.printInfo()\n   \/\/ Output: This pizza has flatbread base with tomato sauce without cheese. It has the following toppings: olives\n\n   \/\/ Or send your custom request directly to the chef!\n   let chef = PizzaBuilder()\n   let customPizza = chef.addFlatbreadBase().addTomatoSauce().addCheese().addOlives().addJalapeno().cook()\n   customPizza.printInfo()\n   \/\/ Output: This pizza has flatbread base with tomato sauce with cheese. It has the following toppings: olives,jalapeno\n\n}\n\nrun()<\/code><\/pre>\n<p>Voc\u00ea pode combinar o Builder com um Diretor, como mostrado pela classe <code>PizzaShop<\/code> no exemplo acima, para pr\u00e9-definir um conjunto de etapas a seguir toda vez que construir uma variante padr\u00e3o do seu produto, ou seja, uma receita espec\u00edfica para suas pizzas.<\/p>\n<p>A \u00fanica quest\u00e3o com este padr\u00e3o de design \u00e9 que ele \u00e9 bastante complexo de configurar e manter. No entanto, adicionar novos recursos dessa maneira \u00e9 mais simples do que com o m\u00e9todo Factory.<\/p>\n<h4>5. Prototype<\/h4>\n<p>O padr\u00e3o de design Prot\u00f3tipo \u00e9 uma maneira r\u00e1pida e simples de criar novos objetos a partir de objetos existentes, clonando.<\/p>\n<p>Um objeto prot\u00f3tipo \u00e9 criado primeiro, o qual pode ser clonado v\u00e1rias vezes para criar novos objetos. Ele \u00e9 \u00fatil quando instanciar diretamente um objeto \u00e9 uma opera\u00e7\u00e3o mais intensiva em recursos em compara\u00e7\u00e3o com a cria\u00e7\u00e3o de uma c\u00f3pia de um objeto existente.<\/p>\n<p>No exemplo abaixo, voc\u00ea ver\u00e1 como pode usar o padr\u00e3o Prot\u00f3tipo para criar novos documentos com base em um documento de modelo definido:<\/p>\n<pre><code class=\"language-js\">\/\/ Defining how a document would look like\nfunction Document() {\n   this.header = \"Acme Co\"\n   this.footer = \"For internal use only\"\n   this.pages = 2\n   this.text = \"\"\n  \n   this.addText = function(text) {\n       this.text += text\n   }\n\n   \/\/ Method to help you see the contents of the object\n   this.printInfo = function() {\n       console.log(\"nnHeader: \" + this.header + \"nFooter: \" + this.footer + \"nPages: \" + this.pages + \"nText: \" + this.text)\n   }\n\n  \n}\n\n\/\/ A protype (or template) for creating new blank documents with boilerplate information\nfunction DocumentPrototype(baseDocument) {\n   this.baseDocument = baseDocument\n  \n   \/\/ This is where the magic happens. A new document object is created and is assigned the values of the current object\n   this.clone = function() {\n       let document = new Document();\n\n       document.header = this.baseDocument.header\n       document.footer = this.baseDocument.footer\n       document.pages = this.baseDocument.pages\n       document.text = this.baseDocument.text\n\n       return document\n   }\n}\n\nfunction run() {\n   \/\/ Create a document to use as the base for the prototype\n   let baseDocument = new Document()\n\n   \/\/ Make some changes to the prototype\n   baseDocument.addText(\"This text was added before cloning and will be common in both documents. \")\n\n   let prototype = new DocumentPrototype(baseDocument)\n\n   \/\/ Create two documents from the prototype\n   let doc1 = prototype.clone()\n   let doc2 = prototype.clone()\n\n   \/\/ Make some changes to both objects\n   doc1.pages = 3\n\n   doc1.addText(\"This is document 1\")\n   doc2.addText(\"This is document 2\")\n\n   \/\/ Print their values\n   doc1.printInfo()\n   \/* Output:\n       Header: Acme Co\n       Footer: For internal use only\n       Pages: 3\n       Text: This text was added before cloning and will be common in both documents. This is document 1\n    *\/\n\n   doc2.printInfo()\n   \/** Output:\n       Header: Acme Co\n       Footer: For internal use only\n       Pages: 2\n       Text: This text was added before cloning and will be common in both documents. This is document 2\n    *\/\n}\n\nrun()<\/code><\/pre>\n<p>O m\u00e9todo Prot\u00f3tipo funciona muito bem em casos em que uma grande parte dos objetos compartilha os mesmos valores ou quando criar um novo objeto do zero \u00e9 bastante custoso. No entanto, pode parecer excessivo em casos em que voc\u00ea n\u00e3o precisa de mais do que algumas inst\u00e2ncias da classe.<\/p>\n<h3>Estrutural<\/h3>\n<p>Padr\u00f5es de projeto estrutural ajudam voc\u00ea a organizar sua l\u00f3gica de neg\u00f3cios, fornecendo formas testadas e comprovadas de estruturar suas aulas. H\u00e1 uma variedade de padr\u00f5es de projeto estrutural que cada um atende a casos de uso \u00fanico.<\/p>\n<h4>6. Adaptador<\/h4>\n<p>Um problema comum ao desenvolver aplicativos \u00e9 permitir a colabora\u00e7\u00e3o entre classes incompat\u00edveis.<\/p>\n<p>Um bom exemplo para entender isso \u00e9 ao manter a compatibilidade retroativa. Se voc\u00ea escrever uma nova vers\u00e3o de uma classe, naturalmente desejar\u00e1 que ela possa ser facilmente usada em todos os lugares onde a vers\u00e3o antiga funcionava. No entanto, se voc\u00ea fizer altera\u00e7\u00f5es incompat\u00edveis, como remover ou atualizar m\u00e9todos que eram cruciais para o funcionamento da vers\u00e3o antiga, poder\u00e1 acabar com uma classe que precisa que todos os seus clientes sejam atualizados para ser executada.<\/p>\n<p>Nesses casos, o padr\u00e3o de design Adapter pode ajudar.<\/p>\n<p>O padr\u00e3o de design Adapter fornece uma abstra\u00e7\u00e3o que faz a ponte entre os m\u00e9todos e propriedades da nova classe e os m\u00e9todos e propriedades da classe antiga. Ele tem a mesma interface da classe antiga, mas cont\u00e9m l\u00f3gica para mapear os m\u00e9todos antigos para os novos m\u00e9todos a fim de executar opera\u00e7\u00f5es semelhantes. Isso \u00e9 semelhante a como um adaptador de tomada atua como um intermedi\u00e1rio entre uma tomada de estilo americano e uma tomada de estilo europeu.<\/p>\n<p>Aqui est\u00e1 um exemplo:<\/p>\n<pre><code class=\"language-js\">\/\/ Old bot\nfunction Robot() {\n\n   this.walk = function(numberOfSteps) {\n       \/\/ code to make the robot walk\n       console.log(\"walked \" + numberOfSteps + \" steps\")\n   }\n\n   this.sit = function() {\n       \/\/ code to make the robot sit\n       console.log(\"sit\")\n   }\n\n}\n\n\/\/ New bot that does not have the walk function anymore\n\/\/ but instead has functions to control each step independently\nfunction AdvancedRobot(botName) {\n   \/\/ the new bot has a name as well\n   this.name = botName\n\n   this.sit = function() {\n       \/\/ code to make the robot sit\n       console.log(\"sit\")\n   }\n\n   this.rightStepForward = function() {\n       \/\/ code to take 1 step from right leg forward\n       console.log(\"right step forward\")\n   }\n\n   this.leftStepForward = function () {\n       \/\/ code to take 1 step from left leg forward\n       console.log(\"left step forward\")\n   }\n}\n\nfunction RobotAdapter(botName) {\n   \/\/ No references to the old interfact since that is usually\n   \/\/ phased out of development\n   const robot = new AdvancedRobot(botName)\n\n   \/\/ The adapter defines the walk function by using the\n   \/\/ two step controls. You now have room to choose which leg to begin\/end with,\n   \/\/ and do something at each step.\n   this.walk = function(numberOfSteps) {\n       for (let i=0; i&lt;numberOfSteps; i++) {\n          \n           if (i % 2 === 0) {\n               robot.rightStepForward()\n           } else {\n               robot.leftStepForward()\n           }\n       }\n   }\n\n   this.sit = robot.sit\n\n}\n\nfunction run() {\n\n   let robot = new Robot()\n\n   robot.sit()\n   \/\/ Output: sit\n   robot.walk(5)\n   \/\/ Output: walked 5 steps\n\n   robot = new RobotAdapter(\"my bot\")\n\n   robot.sit()\n   \/\/ Output: sit\n   robot.walk(5)\n   \/\/ Output:\n   \/\/ right step forward\n   \/\/ left step forward\n   \/\/ right step forward\n   \/\/ left step forward\n   \/\/ right step forward\n\n}\n\nrun()<\/code><\/pre>\n<p>A principal quest\u00e3o com este padr\u00e3o de design \u00e9 que ele adiciona complexidade ao seu c\u00f3digo-fonte. Voc\u00ea j\u00e1 precisava manter duas classes diferentes, e agora voc\u00ea tem outra classe &#8211; o Adaptador &#8211; para manter.<\/p>\n<h4>7. Bridge<\/h4>\n<p>Explicando mais sobre o padr\u00e3o de design Bridge, ele fornece tanto \u00e0 classe quanto ao cliente interfaces separadas, permitindo que eles funcionem mesmo em casos de interfaces nativas incompat\u00edveis.<\/p>\n<p>Isso ajuda no desenvolvimento de uma interface muito desacoplada entre os dois tipos de objetos. Tamb\u00e9m auxilia na melhoria da extensibilidade das interfaces e suas implementa\u00e7\u00f5es, proporcionando m\u00e1xima flexibilidade.<\/p>\n<p>Veja como voc\u00ea pode us\u00e1-lo:<\/p>\n<pre><code class=\"language-js\">\/\/ The TV and speaker share the same interface\nfunction TV() {\n   this.increaseVolume = function() {\n       \/\/ logic to increase TV volume\n   }\n\n   this.decreaseVolume = function() {\n       \/\/ logic to decrease TV volume\n   }\n\n   this.mute = function() {\n       \/\/ logic to mute TV audio\n   }\n}\n\nfunction Speaker() {\n   this.increaseVolume = function() {\n       \/\/ logic to increase speaker volume\n   }\n\n   this.decreaseVolume = function() {\n       \/\/ logic to decrease speaker volume\n   }\n\n   this.mute() = function() {\n       \/\/ logic to mute speaker audio\n   }\n}\n\n\/\/ The two remotes make use of the same common interface\n\/\/ that supports volume up and volume down features\nfunction SimpleRemote(device) {\n   this.pressVolumeDownKey = function() {\n       device.decreaseVolume()\n   }\n\n   this.pressVolumeUpKey = function() {\n       device.increaseVolume()\n   }\n}\n\nfunction AdvancedRemote(device) {\n\n   this.pressVolumeDownKey = function() {\n       device.decreaseVolume()\n   }\n\n   this.pressVolumeUpKey = function() {\n       device.increaseVolume()\n   }\n\n   this.pressMuteKey = function() {\n       device.mute()\n   }\n}\n\nfunction run() {\n\n   let tv = new TV()\n   let speaker = new Speaker()\n\n   let tvSimpleRemote = new SimpleRemote(tv)\n   let tvAdvancedRemote = new AdvancedRemote(tv)\n\n   let speakerSimpleRemote = new SimpleRemote(speaker)\n   let speakerAdvancedRemote = new AdvancedRemote(speaker)\n\n   \/\/ The methods listed in pair below will have the same effect\n   \/\/ on their target devices\n   tvSimpleRemote.pressVolumeDownKey()\n   tvAdvancedRemote.pressVolumeDownKey()\n\n   tvSimpleRemote.pressVolumeUpKey()\n   tvAdvancedRemote.pressVolumeUpKey()\n\n   \/\/ The advanced remote has additional functionality\n   tvAdvancedRemote.pressMuteKey()\n\n   speakerSimpleRemote.pressVolumeDownKey()\n   speakerAdvancedRemote.pressVolumeDownKey()\n\n   speakerSimpleRemote.pressVolumeUpKey()\n   speakerAdvancedRemote.pressVolumeUpKey()\n\n   speakerAdvancedRemote.pressMuteKey()\n}<\/code><\/pre>\n<p>Como voc\u00ea j\u00e1 deve ter adivinhado, o padr\u00e3o Bridge aumenta muito a complexidade da base de c\u00f3digo. Al\u00e9m disso, a maioria das interfaces geralmente acaba com apenas uma implementa\u00e7\u00e3o em casos de uso real, ent\u00e3o voc\u00ea n\u00e3o se beneficia muito da reusabilidade do c\u00f3digo.<\/p>\n<h4 id=\"8-composite\" class=\"has-anchor-hash\">8. Composite<\/h4>\n<p>O padr\u00e3o de design Composite ajuda a estruturar e gerenciar facilmente objetos e entidades semelhantes. A ideia b\u00e1sica por tr\u00e1s do padr\u00e3o Composite \u00e9 que os objetos e seus cont\u00eaineres l\u00f3gicos podem ser representados usando uma \u00fanica classe abstrata (que pode armazenar dados\/m\u00e9todos relacionados ao objeto e refer\u00eancias a si mesma para o cont\u00eainer).<\/p>\n<p>Faz mais sentido usar o padr\u00e3o Composite quando seu modelo de dados se assemelha a uma estrutura de \u00e1rvore. No entanto, n\u00e3o tente transformar um modelo de dados n\u00e3o relacionado a uma \u00e1rvore em um modelo de dados semelhante a uma \u00e1rvore apenas pelo bem de usar o padr\u00e3o Composite, pois isso geralmente pode reduzir muito a flexibilidade.<\/p>\n<p>No exemplo abaixo, voc\u00ea ver\u00e1 como pode usar o padr\u00e3o de design Composite para construir um sistema de embalagem para produtos de eCommerce que tamb\u00e9m pode calcular o valor total do pedido por embalagem:<\/p>\n<pre><code class=\"language-js\">\/\/ A product class, that acts as a Leaf node\nfunction Product(name, price) {\n   this.name = name\n   this.price = price\n\n   this.getTotalPrice = function() {\n       return this.price\n   }\n}\n\n\/\/ A box class, that acts as a parent\/child node\nfunction Box(name) {\n   this.contents = []\n   this.name = name\n\n   \/\/ Helper function to add an item to the box\n   this.add = function(content){\n       this.contents.push(content)\n   }\n\n   \/\/ Helper function to remove an item from the box\n   this.remove = function() {\n       var length = this.contents.length;\n       for (var i = 0; i &lt; length; i++) {\n           if (this.contents[i] === child) {\n               this.contents.splice(i, 1);\n               return;\n           }\n       }\n   }\n\n   \/\/ Helper function to get one item from the box\n   this.getContent = function(position) {\n       return this.contents[position]\n   }\n\n   \/\/ Helper function to get the total count of the items in the box\n   this.getTotalCount = function() {\n       return this.contents.length\n   }\n\n   \/\/ Helper function to calculate the total price of all items in the box\n   this.getTotalPrice = function() {\n       let totalPrice = 0;\n\n       for (let i=0; i &lt; this.getTotalCount(); i++){\n           totalPrice += this.getContent(i).getTotalPrice()\n       }\n\n       return totalPrice\n   }\n}\n\nfunction run() {\n\n   \/\/ Let's create some electronics\n   const mobilePhone = new Product(\"mobile phone,\" 1000)\n   const phoneCase = new Product(\"phone case,\" 30)\n   const screenProtector = new Product(\"screen protector,\" 20)\n\n   \/\/ and some stationery products\n   const pen = new Product(\"pen,\" 2)\n   const pencil = new Product(\"pencil,\" 0.5)\n   const eraser = new Product(\"eraser,\" 0.5)\n   const stickyNotes = new Product(\"sticky notes,\" 10)\n\n   \/\/ and put them in separate boxes\n   const electronicsBox = new Box(\"electronics\")\n   electronicsBox.add(mobilePhone)\n   electronicsBox.add(phoneCase)\n   electronicsBox.add(screenProtector)\n  \n   const stationeryBox = new Box(\"stationery\")\n   stationeryBox.add(pen)\n   stationeryBox.add(pencil)\n   stationeryBox.add(eraser)\n   stationeryBox.add(stickyNotes)\n\n   \/\/ and finally, put them into one big box for convenient shipping\n   const package = new Box('package')\n   package.add(electronicsBox)\n   package.add(stationeryBox)\n\n   \/\/ Here's an easy way to calculate the total order value\n   console.log(\"Total order price: USD \" + package.getTotalPrice())\n   \/\/ Output: USD 1063\n}\n\nrun()<\/code><\/pre>\n<p>A maior desvantagem de usar o padr\u00e3o Composite \u00e9 que as mudan\u00e7as nas interfaces dos componentes podem ser muito desafiadoras no futuro. Projetar as interfaces leva tempo e esfor\u00e7o, e a natureza semelhante a \u00e1rvores do modelo de dados pode tornar muito dif\u00edcil fazer mudan\u00e7as como voc\u00ea desejar.<\/p>\n<h4>9. Decorator<\/h4>\n<p>O padr\u00e3o de design Decorator ajuda a adicionar novas funcionalidades a objetos existentes, simplesmente envolvendo-os dentro de um novo objeto. \u00c9 semelhante a como voc\u00ea pode envolver uma caixa de presente j\u00e1 embrulhada com um novo papel de embrulho quantas vezes quiser: cada embrulho permite adicionar quantas funcionalidades desejar, o que o torna altamente flex\u00edvel.<\/p>\n<p>Do ponto de vista t\u00e9cnico, n\u00e3o h\u00e1 heran\u00e7a envolvida, o que proporciona maior liberdade ao projetar a l\u00f3gica de neg\u00f3cios.<\/p>\n<p>No exemplo abaixo, voc\u00ea ver\u00e1 como o padr\u00e3o Decorator ajuda a adicionar mais funcionalidades a uma classe <code>Customer<\/code> padr\u00e3o<span style=\"font-size: 1.125rem\">:<\/span><\/p>\n<pre><code class=\"language-js\">function Customer(name, age) {\n   this.name = name\n   this.age = age\n\n   this.printInfo = function() {\n       console.log(\"Customer:nName : \" + this.name + \" | Age: \" + this.age)\n   }\n}\n\nfunction DecoratedCustomer(customer, location) {\n   this.customer = customer\n   this.name = customer.name\n   this.age = customer.age\n   this.location = location\n\n   this.printInfo = function() {\n       console.log(\"Decorated Customer:nName: \" + this.name + \" | Age: \" + this.age + \" | Location: \" + this.location)\n   }\n}\n\nfunction run() {\n   let customer = new Customer(\"John,\" 25)\n   customer.printInfo()\n   \/\/ Output:\n   \/\/ Customer:\n   \/\/ Name : John | Age: 25\n\n   let decoratedCustomer = new DecoratedCustomer(customer, \"FL\")\n   decoratedCustomer.printInfo()\n   \/\/ Output:\n   \/\/ Customer:\n   \/\/ Name : John | Age: 25 | Location: FL\n}\n\nrun()<\/code><\/pre>\n<p>As desvantagens desse padr\u00e3o incluem alta complexidade de c\u00f3digo, pois n\u00e3o h\u00e1 um padr\u00e3o definido para adicionar novas funcionalidades usando decoradores. Voc\u00ea pode acabar com muitos decoradores n\u00e3o uniformes e\/ou semelhantes no final do ciclo de desenvolvimento do seu software.<\/p>\n<p>Se voc\u00ea n\u00e3o tiver cuidado ao projetar os decoradores, poder\u00e1 projetar alguns decoradores de forma logicamente dependente de outros. Se isso n\u00e3o for resolvido, remover ou reestruturar os decoradores posteriormente pode causar problemas na estabilidade do seu aplicativo.<\/p>\n<h4>10. Facade<\/h4>\n<p>Ao construir a maioria dos aplicativos do mundo real, a l\u00f3gica de neg\u00f3cio geralmente acaba sendo bastante complexa quando voc\u00ea termina. Voc\u00ea pode acabar com v\u00e1rios objetos e m\u00e9todos envolvidos na execu\u00e7\u00e3o de opera\u00e7\u00f5es principais em seu aplicativo. Manter o controle de suas inicializa\u00e7\u00f5es, depend\u00eancias, a ordem correta de execu\u00e7\u00e3o dos m\u00e9todos, etc., pode ser bastante complicado e propenso a erros se n\u00e3o for feito corretamente.<\/p>\n<p>O padr\u00e3o de design Facade ajuda a criar uma abstra\u00e7\u00e3o entre o ambiente que invoca as opera\u00e7\u00f5es mencionadas acima e os objetos e m\u00e9todos envolvidos na conclus\u00e3o dessas opera\u00e7\u00f5es. Essa abstra\u00e7\u00e3o abriga a l\u00f3gica para inicializar os objetos, controlar suas depend\u00eancias e outras atividades importantes. O ambiente chamador n\u00e3o tem informa\u00e7\u00f5es sobre como uma opera\u00e7\u00e3o \u00e9 executada. Voc\u00ea pode atualizar livremente a l\u00f3gica sem fazer altera\u00e7\u00f5es que quebrem o c\u00f3digo do cliente que faz a chamada.<\/p>\n<p>Aqui est\u00e1 como voc\u00ea pode us\u00e1-lo em um aplicativo:<\/p>\n<pre><code class=\"language-js\">\/**\n* Let's say you're trying to build an online store. It will have multiple components and\n* complex business logic. In the example below, you will find a tiny segment of an online\n* store composed together using the Facade design pattern. The various manager and helper\n* classes are defined first of all.\n*\/\n\n\nfunction CartManager() {\n   this.getItems = function() {\n       \/\/ logic to return items\n       return []\n   }\n  \n   this.clearCart = function() {\n       \/\/ logic to clear cart\n   }\n}\n\nfunction InvoiceManager() {\n   this.createInvoice = function(items) {\n       \/\/ logic to create invoice\n       return {}\n   }\n\n   this.notifyCustomerOfFailure = function(invoice) {\n       \/\/ logic to notify customer\n   }\n\n   this.updateInvoicePaymentDetails = function(paymentResult) {\n       \/\/ logic to update invoice after payment attempt\n   }\n}\n\nfunction PaymentProcessor() {\n   this.processPayment = function(invoice) {\n       \/\/ logic to initiate and process payment\n       return {}\n   }\n}\n\nfunction WarehouseManager() {\n   this.prepareForShipping = function(items, invoice) {\n       \/\/ logic to prepare the items to be shipped\n   }\n}\n\n\/\/ This is where facade comes in. You create an additional interface on top of your\n\/\/ existing interfaces to define the business logic clearly. This interface exposes\n\/\/ very simple, high-level methods for the calling environment.\nfunction OnlineStore() {\n   this.name = \"Online Store\"\n  \n   this.placeOrder = function() {\n       let cartManager = new CartManager()\n       let items = cartManager.getItems()\n\n       let invoiceManager = new InvoiceManager()\n       let invoice = invoiceManager.createInvoice(items)\n      \n       let paymentResult = new PaymentProcessor().processPayment(invoice)\n       invoiceManager.updateInvoicePaymentDetails(paymentResult)\n\n       if (paymentResult.status === 'success') {\n           new WarehouseManager().prepareForShipping(items, invoice)\n           cartManager.clearCart()\n       } else {\n           invoiceManager.notifyCustomerOfFailure(invoice)\n       }\n      \n   }\n}\n\n\/\/ The calling environment is unaware of what goes on when somebody clicks a button to\n\/\/ place the order. You can easily change the underlying business logic without breaking\n\/\/ your calling environment.\nfunction run() {\n   let onlineStore = new OnlineStore()\n\n   onlineStore.placeOrder()\n}<\/code><\/pre>\n<p>Uma desvantagem do uso do padr\u00e3o Facade \u00e9 que ele adiciona uma camada adicional de abstra\u00e7\u00e3o entre a l\u00f3gica do seu neg\u00f3cio e o cliente, exigindo assim manuten\u00e7\u00e3o adicional. Na maioria das vezes, isso aumenta a complexidade geral da base de c\u00f3digo.<\/p>\n<p>Al\u00e9m disso, a classe <code>Facade<\/code> torna-se uma depend\u00eancia obrigat\u00f3ria do funcionamento do seu aplicativo &#8211; o que significa que qualquer erro na classe <code>Facade<\/code> afeta diretamente o funcionamento do seu aplicativo.<\/p>\n<h4>11. Flyweight<\/h4>\n<p>O padr\u00e3o de design Flyweight ajuda a resolver problemas que envolvem objetos com componentes repetidos de maneira eficiente em termos de mem\u00f3ria, permitindo reutilizar os componentes comuns do pool de objetos. Isso ajuda a reduzir a carga na mem\u00f3ria e resulta em tempos de execu\u00e7\u00e3o mais r\u00e1pidos.<\/p>\n<p>No exemplo abaixo, uma frase grande \u00e9 armazenada na mem\u00f3ria usando o padr\u00e3o de design Flyweight. Em vez de armazenar cada caractere \u00e0 medida que ocorre, o programa identifica o conjunto de caracteres distintos usados para escrever o par\u00e1grafo e seus tipos (n\u00famero ou letra) e constr\u00f3i &#8220;flyweights&#8221; reutiliz\u00e1veis para cada caractere, contendo detalhes de qual caractere e tipo s\u00e3o armazenados.<\/p>\n<p>Em seguida, a array principal armazena apenas uma lista de refer\u00eancias para esses &#8220;flyweights&#8221; na ordem em que ocorrem na frase, em vez de armazenar uma inst\u00e2ncia do objeto de caractere sempre que ele ocorre.<\/p>\n<p>Isso reduz pela metade a mem\u00f3ria ocupada pela frase. Tenha em mente que esta \u00e9 uma explica\u00e7\u00e3o muito b\u00e1sica de como processadores de texto armazenam texto.<\/p>\n<pre><code class=\"language-js\">\/\/ A simple Character class that stores the value, type, and position of a character\nfunction Character(value, type, position) {\n   this.value = value\n   this.type = type\n   this.position = position\n}\n\n\/\/ A Flyweight class that stores character value and type combinations\nfunction CharacterFlyweight(value, type) {\n   this.value = value\n   this.type = type\n}\n\n\/\/ A factory to automatically create the flyweights that are not present in the list,\n\/\/ and also generate a count of the total flyweights in the list\nconst CharacterFlyweightFactory = (function () {\n   const flyweights = {}\n\n   return {\n       get: function (value, type) {\n           if (flyweights[value + type] === undefined)\n               flyweights[value + type] = new CharacterFlyweight(value, type)\n\n           return flyweights[value + type]\n       },\n       count: function () {\n           let count = 0;\n           for (var f in flyweights) count++;\n           return count;\n       }\n   }\n})()\n\n\/\/ An enhanced Character class that uses flyweights to store references\n\/\/ to recurring value and type combinations\nfunction CharacterWithFlyweight(value, type, position) {\n   this.flyweight = CharacterFlyweightFactory.get(value, type)\n   this.position = position\n}\n\n\/\/ A helper function to define the type of a character\n\/\/ It identifies numbers as N and everything as A (for alphabets)\nfunction getCharacterType(char) {\n   switch (char) {\n       case \"0\":\n       case \"1\":\n       case \"2\":\n       case \"3\":\n       case \"4\":\n       case \"5\":\n       case \"6\":\n       case \"7\":\n       case \"8\":\n       case \"9\": return \"N\"\n       default:\n           return \"A\"\n\n   }\n}\n\n\/\/ A list class to create an array of Characters from a given string\nfunction CharactersList(str) {\n   chars = []\n   for (let i = 0; i &lt; str.length; i++) {\n       const char = str[i]\n       chars.push(new Character(char, getCharacterType(char), i))\n   }\n\n   return chars\n}\n\n\/\/ A list class to create an array of CharacterWithFlyweights from a given string\nfunction CharactersWithFlyweightsList(str) {\n   chars = []\n   for (let i = 0; i  \" + charactersList.length)\n   \/\/ Output: Character count -&gt; 656\n\n   \/\/ The number of flyweights created is only 31, since only 31 characters are used to write the\n   \/\/ entire paragraph. This means that to store 656 characters, a total of\n   \/\/ (31 * 2 + 656 * 1 = 718) memory blocks are used instead of (656 * 3 = 1968) which would have\n   \/\/ used by the standard array.\n   \/\/ (We have assumed each variable to take up one memory block for simplicity. This\n   \/\/ may vary in real-life scenarios)\n   console.log(\"Flyweights created -&gt; \" + CharacterFlyweightFactory.count())\n   \/\/ Output: Flyweights created -&gt; 31\n\n}\n\nrun()<\/code><\/pre>\n<p>Como voc\u00ea pode ter percebido, o padr\u00e3o Flyweight adiciona complexidade ao design de software, n\u00e3o sendo particularmente intuitivo. Portanto, se economizar mem\u00f3ria n\u00e3o \u00e9 uma preocupa\u00e7\u00e3o urgente para o seu aplicativo, a complexidade adicional do Flyweight pode trazer mais desvantagens do que benef\u00edcios.<\/p>\n<p>Al\u00e9m disso, os &#8220;flyweights&#8221; trocam mem\u00f3ria por efici\u00eancia de processamento, portanto, se voc\u00ea tiver poucos ciclos de CPU dispon\u00edveis, o Flyweight n\u00e3o ser\u00e1 uma boa solu\u00e7\u00e3o para voc\u00ea.<\/p>\n<h4>12. Proxy<\/h4>\n<p>O padr\u00e3o Proxy ajuda a substituir um objeto por outro objeto. Em outras palavras, objetos proxy podem ocupar o lugar de objetos reais (pelos quais s\u00e3o um proxy) e controlar o acesso ao objeto. Esses objetos proxy podem ser usados para realizar algumas a\u00e7\u00f5es antes ou depois que uma solicita\u00e7\u00e3o de invoca\u00e7\u00e3o seja passada para o objeto real.<\/p>\n<p>No exemplo abaixo, voc\u00ea ver\u00e1 como o acesso a uma inst\u00e2ncia de banco de dados \u00e9 controlado por meio de um proxy que realiza algumas verifica\u00e7\u00f5es b\u00e1sicas de valida\u00e7\u00e3o nas solicita\u00e7\u00f5es antes de permitir que elas sejam processadas:<\/p>\n<pre><code class=\"language-js\">function DatabaseHandler() {\n   const data = {}\n\n   this.set = function (key, val) {\n       data[key] = val;\n   }\n   this.get = function (key, val) {\n       return data[key]\n   }\n   this.remove = function (key) {\n       data[key] = null;\n   }\n\n\n}\n\nfunction DatabaseProxy(databaseInstance) {\n\n   this.set = function (key, val) {\n       if (key === \"\") {\n           console.log(\"Invalid input\")\n           return\n       }\n\n       if (val === undefined) {\n           console.log(\"Setting value to undefined not allowed!\")\n           return\n       }\n\n       databaseInstance.set(key, val)\n   }\n\n   this.get = function (key) {\n       if (databaseInstance.get(key) === null) {\n           console.log(\"Element deleted\")\n       }\n\n       if (databaseInstance.get(key) === undefined) {\n           console.log(\"Element not created\")\n       }\n\n       return databaseInstance.get(key)\n   }\n\n   this.remove = function (key) {\n       if (databaseInstance.get(key) === undefined) {\n           console.log(\"Element not added\")\n           return\n       }\n\n       if (databaseInstance.get(key) === null) {\n           console.log(\"Element removed already\")\n           return\n       }\n\n       return databaseInstance.remove(key)\n   }\n\n}\n\nfunction run() {\n   let databaseInstance = new DatabaseHandler()\n\n   databaseInstance.set(\"foo,\" \"bar\")\n   databaseInstance.set(\"foo,\" undefined)\n   console.log(\"#1: \" + databaseInstance.get(\"foo\"))\n   \/\/ #1: undefined\n\n   console.log(\"#2: \" + databaseInstance.get(\"baz\"))\n   \/\/ #2: undefined\n\n   databaseInstance.set(\",\" \"something\")\n\n   databaseInstance.remove(\"foo\")\n   console.log(\"#3: \" + databaseInstance.get(\"foo\"))\n   \/\/ #3: null\n\n   databaseInstance.remove(\"foo\")\n   databaseInstance.remove(\"baz\")\n\n   \/\/ Create a fresh database instance to try the same operations\n   \/\/ using the proxy\n   databaseInstance = new DatabaseHandler()\n   let proxy = new DatabaseProxy(databaseInstance)\n\n   proxy.set(\"foo,\" \"bar\")\n   proxy.set(\"foo,\" undefined)\n   \/\/ Proxy jumps in:\n   \/\/ Output: Setting value to undefined not allowed!\n\n   console.log(\"#1: \" + proxy.get(\"foo\"))\n   \/\/ Original value is retained:\n   \/\/ Output: #1: bar\n\n   console.log(\"#2: \" + proxy.get(\"baz\"))\n   \/\/ Proxy jumps in again\n   \/\/ Output:\n   \/\/ Element not created\n   \/\/ #2: undefined\n\n\n   proxy.set(\",\" \"something\")\n   \/\/ Proxy jumps in again\n   \/\/ Output: Invalid input\n\n   proxy.remove(\"foo\")\n\n   console.log(\"#3: \" + proxy.get(\"foo\"))\n   \/\/ Proxy jumps in again\n   \/\/ Output:\n   \/\/ Element deleted\n   \/\/ #3: null\n\n   proxy.remove(\"foo\")\n   \/\/ Proxy output: Element removed already\n   proxy.remove(\"baz\")\n   \/\/ Proxy output: Element not added\n\n}\n\nrun()<\/code><\/pre>\n<p>Este padr\u00e3o de design \u00e9 amplamente utilizado na ind\u00fastria e ajuda a implementar opera\u00e7\u00f5es pr\u00e9 e p\u00f3s-execu\u00e7\u00e3o facilmente. No entanto, assim como qualquer outro padr\u00e3o de design, ele tamb\u00e9m adiciona complexidade \u00e0 sua base de c\u00f3digo, portanto, tente n\u00e3o us\u00e1-lo se realmente n\u00e3o precisar.<\/p>\n<p>Tamb\u00e9m \u00e9 importante lembrar que, como um objeto adicional est\u00e1 envolvido ao fazer chamadas para o seu objeto real, pode haver alguma lat\u00eancia devido \u00e0s opera\u00e7\u00f5es de processamento adicionais. Otimizar o desempenho do seu objeto principal agora tamb\u00e9m envolve otimizar os m\u00e9todos do seu proxy para obter um melhor desempenho.<\/p>\n<h3 id=\"behavioral-1\" class=\"has-anchor-hash\">Behavioral<\/h3>\n<p>Os padr\u00f5es de design comportamental ajudam a resolver problemas relacionados \u00e0 forma como os objetos interagem entre si. Isso pode envolver o compartilhamento ou a transfer\u00eancia de responsabilidade\/controle entre objetos para concluir opera\u00e7\u00f5es conjuntas. Tamb\u00e9m pode envolver a passagem\/compartilhamento de dados entre v\u00e1rios objetos da maneira mais eficiente poss\u00edvel.<\/p>\n<h4>13. Chain of Responsibility<\/h4>\n<p>O padr\u00e3o Chain of Responsibility \u00e9 um dos padr\u00f5es de design comportamentais mais simples. Ele \u00e9 \u00fatil quando voc\u00ea est\u00e1 projetando a l\u00f3gica para opera\u00e7\u00f5es que podem ser tratadas por v\u00e1rios manipuladores.<\/p>\n<p>Similar ao funcionamento da escalada de problemas em equipes de suporte, o controle \u00e9 passado por uma cadeia de manipuladores, e o manipulador respons\u00e1vel por tomar uma a\u00e7\u00e3o completa a opera\u00e7\u00e3o. Esse padr\u00e3o de design \u00e9 frequentemente usado no design de interfaces de usu\u00e1rio, onde v\u00e1rias camadas de componentes podem lidar com um evento de entrada do usu\u00e1rio, como um toque ou um deslize.<\/p>\n<p>Abaixo, voc\u00ea ver\u00e1 um exemplo de escalonamento de reclama\u00e7\u00e3o usando o padr\u00e3o Chain of Responsibility. A reclama\u00e7\u00e3o ser\u00e1 tratada pelos manipuladores com base em sua gravidade:<\/p>\n<pre><code class=\"language-js\">\/\/ Complaint class that stores title and severity of a complaint\n\/\/ Higher value of severity indicates a more severe complaint\nfunction Complaint (title, severity) {\n    this.title = title\n    this.severity = severity\n}\n\n\/\/ Base level handler that receives all complaints\nfunction Representative () {\n    \/\/ If this handler can not handle the complaint, it will be forwarded to the next level\n    this.nextLevel = new Management()\n\n    this.handleComplaint = function (complaint) {\n        if (complaint.severity === 0)\n            console.log(\"Representative resolved the following complaint: \" + complaint.title)\n        else\n            this.nextLevel.handleComplaint(complaint)\n    }\n}\n\n\/\/ Second level handler to handle complaints of severity 1\nfunction Management() {\n    \/\/ If this handler can not handle the complaint, it will be forwarded to the next level\n    this.nextLevel = new Leadership()\n\n    this.handleComplaint = function (complaint) {\n        if (complaint.severity === 1)\n            console.log(\"Management resolved the following complaint: \" + complaint.title)\n        else\n            this.nextLevel.handleComplaint(complaint)\n    }\n}\n\n\/\/ Highest level handler that handles all complaints unhandled so far\nfunction Leadership() {\n    this.handleComplaint = function (complaint) {\n        console.log(\"Leadership resolved the following complaint: \" + complaint.title)\n    }\n}\n\nfunction run() {\n    \/\/ Create an instance of the base level handler\n    let customerSupport = new Representative()\n\n    \/\/ Create multiple complaints of varying severity and pass them to the base handler\n\n    let complaint1 = new Complaint(\"Submit button doesn't work,\" 0)\n    customerSupport.handleComplaint(complaint1)\n    \/\/ Output: Representative resolved the following complaint: Submit button doesn't work\n\n    let complaint2 = new Complaint(\"Payment failed,\" 1)\n    customerSupport.handleComplaint(complaint2)\n    \/\/ Output: Management resolved the following complaint: Payment failed\n\n    let complaint3 = new Complaint(\"Employee misdemeanour,\" 2)\n    customerSupport.handleComplaint(complaint3)\n    \/\/ Output: Leadership resolved the following complaint: Employee misdemeanour\n}\n\nrun()<\/code><\/pre>\n<p>O problema \u00f3bvio com esse design \u00e9 que ele \u00e9 linear, ent\u00e3o pode haver uma certa lat\u00eancia ao lidar com uma opera\u00e7\u00e3o quando um grande n\u00famero de manipuladores est\u00e1 encadeado uns aos outros.<\/p>\n<p>Manter o controle de todos os manipuladores pode ser outro ponto problem\u00e1tico, pois pode ficar bastante bagun\u00e7ado ap\u00f3s um certo n\u00famero de manipuladores. A depura\u00e7\u00e3o tamb\u00e9m \u00e9 um pesadelo, j\u00e1 que cada solicita\u00e7\u00e3o pode terminar em um manipulador diferente, tornando dif\u00edcil padronizar o <a href=\"https:\/\/kinsta.com\/pt\/blog\/como-depurar-codigo-no-node-js\/\">processo de registro e depura\u00e7\u00e3o<\/a>.<\/p>\n<h4>14. Iterator<\/h4>\n<p>O padr\u00e3o Iterator \u00e9 bastante simples e \u00e9 amplamente utilizado em quase todas as linguagens de programa\u00e7\u00e3o orientadas a objetos modernas. Se voc\u00ea se encontrar diante da tarefa de percorrer uma lista de objetos que n\u00e3o s\u00e3o todos do mesmo tipo, os m\u00e9todos de itera\u00e7\u00e3o normais, como loops for, podem se tornar bastante confusos &#8211; especialmente se voc\u00ea tamb\u00e9m estiver escrevendo l\u00f3gica de neg\u00f3cios dentro deles.<\/p>\n<p>O padr\u00e3o Iterator pode ajud\u00e1-lo a isolar a l\u00f3gica de itera\u00e7\u00e3o e processamento de suas listas da l\u00f3gica de neg\u00f3cios principal.<\/p>\n<p>Veja como voc\u00ea pode us\u00e1-lo em uma lista bastante b\u00e1sica com v\u00e1rios tipos de elementos:<\/p>\n<pre><code class=\"language-js\">\/\/ Iterator for a complex list with custom methods\nfunction Iterator(list) {\n   this.list = list\n   this.index = 0\n\n   \/\/ Fetch the current element\n   this.current = function() {\n       return this.list[this.index]\n   }\n\n   \/\/ Fetch the next element in the list\n   this.next = function() {\n       return this.list[this.index++]\n   }\n\n   \/\/ Check if there is another element in the list\n   this.hasNext = function() {\n       return this.index &lt; this.list.length\n   }\n\n   \/\/ Reset the index to point to the initial element\n   this.resetIndex = function() {\n       this.index = 0\n   }\n\n   \/\/ Run a forEach loop over the list\n   this.forEach = function(callback) {\n       for (let element = this.next(); this.index &lt;= this.list.length; element = this.next()) {\n           callback(element)\n       }\n   }\n}\n\nfunction run() {\n   \/\/ A complex list with elements of multiple data types\n   let list = [\"Lorem ipsum,\" 9, [\"lorem ipsum dolor,\" true], false]\n\n   \/\/ Create an instance of the iterator and pass it the list\n   let iterator = new Iterator(list)\n\n   \/\/ Log the first element\n   console.log(iterator.current())\n   \/\/ Output: Lorem ipsum\n\n   \/\/ Print all elements of the list using the iterator's methods\n   while (iterator.hasNext()) {\n       console.log(iterator.next())\n       \/**\n        * Output:\n        * Lorem ipsum\n        * 9\n        * [ 'lorem ipsum dolor', true ]\n        * false\n        *\/\n   }\n\n   \/\/ Reset the iterator's index to the first element\n   iterator.resetIndex()\n\n   \/\/ Use the custom iterator to pass an effect that will run for each element of the list\n   iterator.forEach(function (element) {\n       console.log(element)\n   })\n   \/**\n    * Output:\n    * Lorem ipsum\n    * 9\n    * [ 'lorem ipsum dolor', true ]\n    * false\n    *\/\n}\n\nrun()<\/code><\/pre>\n<p>N\u00e3o \u00e9 preciso dizer que esse padr\u00e3o pode ser desnecessariamente complexo para listas sem m\u00faltiplos tipos de elementos. Al\u00e9m disso, se houver muitos tipos de elementos em uma lista, pode se tornar dif\u00edcil gerenci\u00e1-los.<\/p>\n<p>A chave \u00e9 identificar se voc\u00ea realmente precisa de um iterador com base na sua lista e suas possibilidades futuras de mudan\u00e7a. Al\u00e9m disso, o padr\u00e3o Iterator \u00e9 \u00fatil apenas em listas, e as listas \u00e0s vezes podem limitar o acesso ao seu modo linear. Outras estruturas de dados podem oferecer benef\u00edcios de desempenho ainda maiores.<\/p>\n<h4>15. Mediador<\/h4>\n<p>\u00c0s vezes, o design do seu aplicativo pode exigir que voc\u00ea trabalhe com um grande n\u00famero de objetos distintos que possuem v\u00e1rios tipos de l\u00f3gica de neg\u00f3cios e muitas vezes dependem uns dos outros. Lidar com as depend\u00eancias pode ser complicado, pois voc\u00ea precisa acompanhar como esses objetos trocam dados e controle entre si.<\/p>\n<p>O padr\u00e3o de design Mediator tem como objetivo ajud\u00e1-lo a resolver esse problema, isolando a l\u00f3gica de intera\u00e7\u00e3o desses objetos em um objeto separado.<\/p>\n<p>Esse objeto separado \u00e9 conhecido como o mediador e \u00e9 respons\u00e1vel por realizar o trabalho por meio de suas classes de n\u00edvel inferior. Seu cliente ou ambiente de chamada tamb\u00e9m interagir\u00e1 com o mediador em vez das classes de n\u00edvel inferior.<\/p>\n<p>Aqui est\u00e1 um exemplo do padr\u00e3o de design Mediator em a\u00e7\u00e3o:<\/p>\n<pre><code class=\"language-js\">\/\/ Writer class that receives an assignment, writes it in 2 seconds, and marks it as finished\nfunction Writer(name, manager) {\n    \n    \/\/ Reference to the manager, writer's name, and a busy flag that the manager uses while assigning the article\n    this.manager = manager\n    this.name = name\n    this.busy = false\n\n    this.startWriting = function (assignment) {\n        console.log(this.name + \" started writing \"\" + assignment + \"\"\")\n        this.assignment = assignment\n        this.busy = true\n\n        \/\/ 2 s timer to replicate manual action\n        setTimeout(() =&gt; { this.finishWriting() }, 2000)\n    }\n\n    this.finishWriting = function () {\n        if (this.busy === true) {\n            console.log(this.name + \" finished writing \"\" + this.assignment + \"\"\")\n            this.busy = false\n            return this.manager.notifyWritingComplete(this.assignment)\n        } else {\n            console.log(this.name + \" is not writing any article\")\n        }\n    }\n}\n\n\/\/ Editor class that receives an assignment, edits it in 3 seconds, and marks it as finished\nfunction Editor(name, manager) {\n    \n    \/\/ Reference to the manager, writer's name, and a busy flag that the manager uses while assigning the article\n    this.manager = manager\n    this.name = name\n    this.busy = false\n\n    this.startEditing = function (assignment) {\n        console.log(this.name + \" started editing \"\" + assignment + \"\"\")\n        this.assignment = assignment\n        this.busy = true\n\n        \/\/ 3 s timer to replicate manual action\n        setTimeout(() =&gt; { this.finishEditing() }, 3000)\n    }\n\n    this.finishEditing = function () {\n        if (this.busy === true) {\n            console.log(this.name + \" finished editing \"\" + this.assignment + \"\"\")\n            this.manager.notifyEditingComplete(this.assignment)\n            this.busy = false\n        } else {\n            console.log(this.name + \" is not editing any article\")\n        }\n    }\n}\n\n\/\/ The mediator class\nfunction Manager() {\n    \/\/ Store arrays of workers\n    this.editors = []\n    this.writers = []\n\n    this.setEditors = function (editors) {\n        this.editors = editors\n    }\n    this.setWriters = function (writers) {\n        this.writers = writers\n    }\n\n    \/\/ Manager receives new assignments via this method\n    this.notifyNewAssignment = function (assignment) {\n        let availableWriter = this.writers.find(function (writer) {\n            return writer.busy === false\n        })\n        availableWriter.startWriting(assignment)\n        return availableWriter\n    }\n\n    \/\/ Writers call this method to notify they're done writing\n    this.notifyWritingComplete = function (assignment) {\n        let availableEditor = this.editors.find(function (editor) {\n            return editor.busy === false\n        })\n        availableEditor.startEditing(assignment)\n        return availableEditor\n    }\n\n    \/\/ Editors call this method to notify they're done editing\n    this.notifyEditingComplete = function (assignment) {\n        console.log(\"\"\" + assignment + \"\" is ready to publish\")\n    }\n\n}\n\nfunction run() {\n    \/\/ Create a manager\n    let manager = new Manager()\n\n    \/\/ Create workers\n    let editors = [\n        new Editor(\"Ed,\" manager),\n        new Editor(\"Phil,\" manager),\n    ]\n\n    let writers = [\n        new Writer(\"Michael,\" manager),\n        new Writer(\"Rick,\" manager),\n    ]\n\n    \/\/ Attach workers to manager\n    manager.setEditors(editors)\n    manager.setWriters(writers)\n\n    \/\/ Send two assignments to manager\n    manager.notifyNewAssignment(\"var vs let in JavaScript\")\n    manager.notifyNewAssignment(\"JS promises\")\n\n    \/**\n     * Output:\n     * Michael started writing \"var vs let in JavaScript\"\n     * Rick started writing \"JS promises\"\n     * \n     * After 2s, output:\n     * Michael finished writing \"var vs let in JavaScript\"\n     * Ed started editing \"var vs let in JavaScript\"\n     * Rick finished writing \"JS promises\"\n     * Phil started editing \"JS promises\"\n     *\n     * After 3s, output:\n     * Ed finished editing \"var vs let in JavaScript\"\n     * \"var vs let in JavaScript\" is ready to publish\n     * Phil finished editing \"JS promises\"\n     * \"JS promises\" is ready to publish\n     *\/\n\n}\n\nrun()<\/code><\/pre>\n<p>Embora o mediador forne\u00e7a ao design do seu aplicativo desacoplamento e muita flexibilidade, no final das contas, \u00e9 mais uma classe que voc\u00ea precisa manter. Voc\u00ea deve avaliar se o seu design realmente pode se beneficiar de um mediador antes de escrev\u00ea-lo, para n\u00e3o acabar adicionando complexidade desnecess\u00e1ria \u00e0 sua base de c\u00f3digo.<\/p>\n<p>Tamb\u00e9m \u00e9 importante ter em mente que, mesmo que a classe do mediador n\u00e3o contenha nenhuma l\u00f3gica de neg\u00f3cio direta, ela ainda cont\u00e9m muito c\u00f3digo que \u00e9 crucial para o funcionamento do seu aplicativo e, portanto, pode se tornar bastante complexa rapidamente.<\/p>\n<h4>16. Memento<\/h4>\n<p>A cria\u00e7\u00e3o de vers\u00f5es de objetos \u00e9 outro problema comum que voc\u00ea enfrentar\u00e1 ao desenvolver aplicativos. H\u00e1 muitos casos de uso onde voc\u00ea precisa manter o hist\u00f3rico de um objeto, suportar rollbacks f\u00e1ceis e, at\u00e9 mesmo, suportar a revers\u00e3o desses rollbacks. Escrever a l\u00f3gica para tais aplicativos pode ser dif\u00edcil.<\/p>\n<p>O padr\u00e3o de design do Memento tem o objetivo de resolver este problema facilmente.<\/p>\n<p>Um memento \u00e9 considerado uma imagem instant\u00e2nea de um objeto em um determinado momento no tempo. O padr\u00e3o de design Memento utiliza esses mementos para preservar instant\u00e2neos do objeto \u00e0 medida que ele \u00e9 alterado ao longo do tempo. Quando voc\u00ea precisa reverter para uma vers\u00e3o antiga, basta recuperar o memento correspondente.<\/p>\n<p>Aqui est\u00e1 como voc\u00ea pode implement\u00e1-lo em um aplicativo de processamento de texto:<\/p>\n<pre><code class=\"language-js\">\/\/ The memento class that can hold one snapshot of the Originator class - document\nfunction Text(contents) {\n    \/\/ Contents of the document\n    this.contents = contents\n\n    \/\/ Accessor function for contents\n    this.getContents = function () {\n        return this.contents\n    }\n\n    \/\/ Helper function to calculate word count for the current document\n    this.getWordCount = function () {\n        return this.contents.length\n    }\n}\n\n\/\/ The originator class that holds the latest version of the document\nfunction Document(contents) {\n    \/\/ Holder for the memento, i.e., the text of the document\n    this.text = new Text(contents)\n\n    \/\/ Function to save new contents as a memento\n    this.save = function (contents) {\n        this.text = new Text(contents)\n        return this.text\n    }\n\n    \/\/ Function to revert to an older version of the text using a memento\n    this.restore = function (text) {\n        this.text = new Text(text.getContents())\n    }\n\n    \/\/ Helper function to get the current memento\n    this.getText = function () {\n        return this.text\n    }\n\n    \/\/ Helper function to get the word count of the current document\n    this.getWordCount = function () {\n        return this.text.getWordCount()\n    }\n}\n\n\/\/ The caretaker class that providers helper functions to modify the document\nfunction DocumentManager(document) {\n    \/\/ Holder for the originator, i.e., the document\n    this.document = document\n\n    \/\/ Array to maintain a list of mementos\n    this.history = []\n\n    \/\/ Add the initial state of the document as the first version of the document\n    this.history.push(document.getText())\n\n    \/\/ Helper function to get the current contents of the documents\n    this.getContents = function () {\n        return this.document.getText().getContents()\n    }\n\n    \/\/ Helper function to get the total number of versions available for the document\n    this.getVersionCount = function () {\n        return this.history.length\n    }\n\n    \/\/ Helper function to get the complete history of the document\n    this.getHistory = function () {\n        return this.history.map(function (element) {\n            return element.getContents()\n        })\n\n    }\n\n    \/\/ Function to overwrite the contents of the document\n    this.overwrite = function (contents) {\n        let newVersion = this.document.save(contents)\n        this.history.push(newVersion)\n    }\n\n    \/\/ Function to append new content to the existing contents of the document\n    this.append = function (contents) {\n        let currentVersion = this.history[this.history.length - 1]\n        let newVersion\n        if (currentVersion === undefined)\n            newVersion = this.document.save(contents)\n        else\n            newVersion = this.document.save(currentVersion.getContents() + contents)\n        this.history.push(newVersion)\n    }\n\n    \/\/ Function to delete all the contents of the document\n    this.delete = function () {\n        this.history.push(this.document.save(\"\"))\n    }\n\n    \/\/ Function to get a particular version of the document\n    this.getVersion = function (versionNumber) {\n        return this.history[versionNumber - 1]\n    }\n\n    \/\/ Function to undo the last change\n    this.undo = function () {\n        let previousVersion = this.history[this.history.length - 2]\n        this.document.restore(previousVersion)\n        this.history.push(previousVersion)\n    }\n\n    \/\/ Function to revert the document to a previous version\n    this.revertToVersion = function (version) {\n        let previousVersion = this.history[version - 1]\n        this.document.restore(previousVersion)\n        this.history.push(previousVersion)\n    }\n\n    \/\/ Helper function to get the total word count of the document\n    this.getWordCount = function () {\n        return this.document.getWordCount()\n    }\n\n}\n\nfunction run() {\n    \/\/ Create a document\n    let blogPost = new Document(\"\")\n\n    \/\/ Create a caretaker for the document\n    let blogPostManager = new DocumentManager(blogPost)\n\n    \/\/ Change #1: Add some text\n    blogPostManager.append(\"Hello World!\")\n    console.log(blogPostManager.getContents())\n    \/\/ Output: Hello World!\n\n    \/\/ Change #2: Add some more text\n    blogPostManager.append(\" This is the second entry in the document\")\n    console.log(blogPostManager.getContents())\n    \/\/ Output: Hello World! This is the second entry in the document\n\n    \/\/ Change #3: Overwrite the document with some new text\n    blogPostManager.overwrite(\"This entry overwrites everything in the document\")\n    console.log(blogPostManager.getContents())\n    \/\/ Output: This entry overwrites everything in the document\n\n    \/\/ Change #4: Delete the contents of the document\n    blogPostManager.delete()\n    console.log(blogPostManager.getContents())\n    \/\/ Empty output\n\n    \/\/ Get an old version of the document\n    console.log(blogPostManager.getVersion(2).getContents())\n    \/\/ Output: Hello World!\n\n    \/\/ Change #5: Go back to an old version of the document\n    blogPostManager.revertToVersion(3)\n    console.log(blogPostManager.getContents())\n    \/\/ Output: Hello World! This is the second entry in the document\n\n    \/\/ Get the word count of the current document\n    console.log(blogPostManager.getWordCount())\n    \/\/ Output: 53\n\n    \/\/ Change #6: Undo the last change\n    blogPostManager.undo()\n    console.log(blogPostManager.getContents())\n    \/\/ Empty output\n\n    \/\/ Get the total number of versions for the document\n    console.log(blogPostManager.getVersionCount())\n    \/\/ Output: 7\n\n    \/\/ Get the complete history of the document\n    console.log(blogPostManager.getHistory())\n    \/**\n     * Output:\n     * [\n     *   '',\n     *   'Hello World!',\n     *   'Hello World! This is the second entry in the document',\n     *   'This entry overwrites everything in the document',\n     *   '',\n     *   'Hello World! This is the second entry in the document',\n     *   ''\n     * ]\n     *\/\n}\n\nrun()<\/code><\/pre>\n<p>Embora o padr\u00e3o de design Memento seja uma \u00f3tima solu\u00e7\u00e3o para gerenciar o hist\u00f3rico de um objeto, ele pode consumir muitos recursos. Como cada memento \u00e9 praticamente uma c\u00f3pia do objeto, pode aumentar rapidamente o consumo de mem\u00f3ria do seu aplicativo se n\u00e3o for usado com modera\u00e7\u00e3o.<\/p>\n<p>Com um grande n\u00famero de objetos, o gerenciamento de seus ciclos de vida tamb\u00e9m pode ser uma tarefa tediosa. Al\u00e9m de tudo isso, as classes <code>Originator<\/code> e <code>Caretaker<\/code> geralmente est\u00e3o intimamente acopladas, o que adiciona complexidade \u00e0 sua base de c\u00f3digo.<\/p>\n<h4>17. Observer<\/h4>\n<p>O padr\u00e3o Observer fornece uma solu\u00e7\u00e3o alternativa para o problema de intera\u00e7\u00e3o entre v\u00e1rios objetos (visto anteriormente no padr\u00e3o Mediator).<\/p>\n<p>Em vez de permitir que cada objeto se comunique entre si por meio de um mediador designado, o padr\u00e3o Observer permite que eles se observem mutuamente. Os objetos s\u00e3o projetados para emitir eventos quando est\u00e3o tentando enviar dados ou controle, e outros objetos que est\u00e3o &#8220;ouvindo&#8221; esses eventos podem ent\u00e3o receb\u00ea-los e interagir com base em seu conte\u00fado.<\/p>\n<p>Aqui est\u00e1 uma demonstra\u00e7\u00e3o simples de enviar newsletters para v\u00e1rias pessoas usando o padr\u00e3o Observer:<\/p>\n<pre><code class=\"language-js\">\/\/ The newsletter class that can send out posts to its subscribers\nfunction Newsletter() {\n   \/\/ Maintain a list of subscribers\n   this.subscribers = []\n\n   \/\/ Subscribe a reader by adding them to the subscribers' list\n   this.subscribe = function(subscriber) {\n       this.subscribers.push(subscriber)\n   }\n\n   \/\/ Unsubscribe a reader by removing them from the subscribers' list\n   this.unsubscribe = function(subscriber) {\n       this.subscribers = this.subscribers.filter(\n           function (element) {\n               if (element !== subscriber) return element\n           }\n       )\n   }\n\n   \/\/ Publish a post by calling the receive function of all subscribers\n   this.publish = function(post) {\n       this.subscribers.forEach(function(element) {\n           element.receiveNewsletter(post)\n       })\n   }\n}\n\n\/\/ The reader class that can subscribe to and receive updates from newsletters\nfunction Reader(name) {\n   this.name = name\n\n   this.receiveNewsletter = function(post) {\n       console.log(\"Newsletter received by \" + name + \"!: \" + post)\n   }\n\n}\n\nfunction run() {\n   \/\/ Create two readers\n   let rick = new Reader(\"ed\")\n   let morty = new Reader(\"morty\")\n\n   \/\/ Create your newsletter\n   let newsletter = new Newsletter()\n\n   \/\/ Subscribe a reader to the newsletter\n   newsletter.subscribe(rick)\n\n   \/\/ Publish the first post\n   newsletter.publish(\"This is the first of the many posts in this newsletter\")\n   \/**\n    * Output:\n    * Newsletter received by ed!: This is the first of the many posts in this newsletter\n    *\/\n\n   \/\/ Subscribe another reader to the newsletter\n   newsletter.subscribe(morty)\n\n   \/\/ Publish the second post\n   newsletter.publish(\"This is the second of the many posts in this newsletter\")\n   \/**\n    * Output:\n    * Newsletter received by ed!: This is the second of the many posts in this newsletter\n    * Newsletter received by morty!: This is the second of the many posts in this newsletter\n    *\/\n\n   \/\/ Unsubscribe the first reader\n   newsletter.unsubscribe(rick)\n\n   \/\/ Publish the third post\n   newsletter.publish(\"This is the third of the many posts in this newsletter\")\n   \/**\n    * Output:\n    * Newsletter received by morty!: This is the third of the many posts in this newsletter\n    *\/\n\n}\n\nrun()<\/code><\/pre>\n<p>Embora o padr\u00e3o Observer seja uma maneira elegante de controlar e transmitir dados, ele \u00e9 mais adequado a situa\u00e7\u00f5es em que h\u00e1 um grande n\u00famero de remetentes e destinat\u00e1rios interagindo entre si por meio de um n\u00famero limitado de conex\u00f5es. Se os objetos fizessem conex\u00f5es individuais um a um, perder\u00edamos a vantagem de publicar e se inscrever em eventos, pois sempre haveria apenas um inscrito para cada publicador (quando seria melhor lidar com uma comunica\u00e7\u00e3o direta entre eles).<\/p>\n<p>Al\u00e9m disso, o padr\u00e3o Observer pode levar a problemas de desempenho se os eventos de inscri\u00e7\u00e3o n\u00e3o forem tratados adequadamente. Se um objeto continuar se inscrevendo em outro objeto mesmo quando n\u00e3o precisar, ele <a href=\"https:\/\/en.wikipedia.org\/wiki\/Lapsed_listener_problem\">n\u00e3o ser\u00e1 eleg\u00edvel para coleta de lixo<\/a> e aumentar\u00e1 o consumo de mem\u00f3ria do aplicativo.<\/p>\n<h4>18. State<\/h4>\n<p>O padr\u00e3o de design State \u00e9 um dos padr\u00f5es de design mais utilizados em toda a ind\u00fastria de desenvolvimento de software. Os populares <a href=\"https:\/\/kinsta.com\/pt\/blog\/bibliotecas-javascript\/\">frameworks JavaScript<\/a> como <a href=\"https:\/\/reactjs.org\/docs\/state-and-lifecycle.html\">React<\/a> e <a href=\"https:\/\/medium.com\/olricdigital\/introduction-to-state-management-in-angular-v2-ef6f5144bade\">Angular<\/a> confiam fortemente no padr\u00e3o State para gerenciar dados e comportamentos de aplicativos com base nesses dados.<\/p>\n<p>Em termos simples, o padr\u00e3o de design State \u00e9 \u00fatil em situa\u00e7\u00f5es em que voc\u00ea pode definir estados definitivos de uma entidade (que pode ser um componente, uma p\u00e1gina, um aplicativo ou uma m\u00e1quina) e a entidade tem uma rea\u00e7\u00e3o predefinida \u00e0 mudan\u00e7a de estado.<\/p>\n<p>Digamos que voc\u00ea esteja tentando construir um processo de inscri\u00e7\u00e3o para empr\u00e9stimo. Cada etapa do processo de inscri\u00e7\u00e3o pode ser definida como um estado.<\/p>\n<p>Embora o cliente normalmente veja uma pequena lista de estados simplificados de sua inscri\u00e7\u00e3o (pendente, em an\u00e1lise, aceito e rejeitado), pode haver outras etapas envolvidas internamente. Em cada uma dessas etapas, a inscri\u00e7\u00e3o ser\u00e1 atribu\u00edda a uma pessoa espec\u00edfica e poder\u00e1 ter requisitos \u00fanicos.<\/p>\n<p>O sistema \u00e9 projetado de tal forma que, no final do processamento de um estado, o estado \u00e9 atualizado para o pr\u00f3ximo da fila e o pr\u00f3ximo conjunto relevante de etapas \u00e9 iniciado.<\/p>\n<p>Aqui est\u00e1 como voc\u00ea pode construir um sistema de gerenciamento de tarefas usando o padr\u00e3o de design State:<\/p>\n<pre><code class=\"language-js\">\/\/ Create titles for all states of a task\nconst STATE_TODO = \"TODO\"\nconst STATE_IN_PROGRESS = \"IN_PROGRESS\"\nconst STATE_READY_FOR_REVIEW = \"READY_FOR_REVIEW\"\nconst STATE_DONE = \"DONE\"\n\n\/\/ Create the task class with a title, assignee, and duration of the task\nfunction Task(title, assignee) {\n    this.title = title\n    this.assignee = assignee\n\n    \/\/ Helper function to update the assignee of the task\n    this.setAssignee = function (assignee) {\n        this.assignee = assignee\n    }\n\n    \/\/ Function to update the state of the task\n    this.updateState = function (state) {\n\n        switch (state) {\n            case STATE_TODO:\n                this.state = new TODO(this)\n                break\n            case STATE_IN_PROGRESS:\n                this.state = new IN_PROGRESS(this)\n                break\n            case STATE_READY_FOR_REVIEW:\n                this.state = new READY_FOR_REVIEW(this)\n                break\n            case STATE_DONE:\n                this.state = new DONE(this)\n                break\n            default:\n                return\n        }\n        \/\/ Invoke the callback function for the new state after it is set\n        this.state.onStateSet()\n    }\n\n    \/\/ Set the initial state of the task as TODO\n    this.updateState(STATE_TODO)\n}\n\n\/\/ TODO state\nfunction TODO(task) {\n\n    this.onStateSet = function () {\n        console.log(task.assignee + \" notified about new task \"\" + task.title + \"\"\")\n    }\n}\n\n\/\/ IN_PROGRESS state\nfunction IN_PROGRESS(task) {\n\n    this.onStateSet = function () {\n        console.log(task.assignee + \" started working on the task \"\" + task.title + \"\"\")\n    }\n}\n\n\/\/ READY_FOR_REVIEW state that updates the assignee of the task to be the manager of the developer\n\/\/ for the review\nfunction READY_FOR_REVIEW(task) {\n    this.getAssignee = function () {\n        return \"Manager 1\"\n    }\n\n    this.onStateSet = function () {\n        task.setAssignee(this.getAssignee())\n        console.log(task.assignee + \" notified about completed task \"\" + task.title + \"\"\")\n    }\n}\n\n\/\/ DONE state that removes the assignee of the task since it is now completed\nfunction DONE(task) {\n    this.getAssignee = function () {\n        return \"\"\n    }\n\n    this.onStateSet = function () {\n        task.setAssignee(this.getAssignee())\n        console.log(\"Task \"\" + task.title + \"\" completed\")\n    }\n}\n\nfunction run() {\n    \/\/ Create a task\n    let task1 = new Task(\"Create a login page,\" \"Developer 1\")\n    \/\/ Output: Developer 1 notified about new task \"Create a login page\"\n\n    \/\/ Set it to IN_PROGRESS\n    task1.updateState(STATE_IN_PROGRESS)\n    \/\/ Output: Developer 1 started working on the task \"Create a login page\"\n\n    \/\/ Create another task\n    let task2 = new Task(\"Create an auth server,\" \"Developer 2\")\n    \/\/ Output: Developer 2 notified about new task \"Create an auth server\"\n\n\n    \/\/ Set it to IN_PROGRESS as well\n    task2.updateState(STATE_IN_PROGRESS)\n    \/\/ Output: Developer 2 started working on the task \"Create an auth server\"\n\n    \/\/ Update the states of the tasks until they are done\n    task2.updateState(STATE_READY_FOR_REVIEW)\n    \/\/ Output: Manager 1 notified about completed task \"Create an auth server\"\n    task1.updateState(STATE_READY_FOR_REVIEW)\n    \/\/ Output: Manager 1 notified about completed task \"Create a login page\"\n\n\n    task1.updateState(STATE_DONE)\n    \/\/ Output: Task \"Create a login page\" completed\n    task2.updateState(STATE_DONE)\n    \/\/ Output: Task \"Create an auth server\" completed\n\n}\n\nrun()<\/code><\/pre>\n<p>Embora o padr\u00e3o State fa\u00e7a um \u00f3timo trabalho ao separar as etapas de um processo, pode se tornar extremamente dif\u00edcil de manter em aplicativos grandes que possuem v\u00e1rios estados.<\/p>\n<p>Al\u00e9m disso, se o seu design de processo permite mais do que apenas mover-se linearmente por todos os estados, voc\u00ea ter\u00e1 que escrever e manter mais c\u00f3digo, j\u00e1 que cada transi\u00e7\u00e3o de estado precisa ser tratada separadamente.<\/p>\n<h4>19. Strategy<\/h4>\n<p>Tamb\u00e9m conhecido como padr\u00e3o Policy, o padr\u00e3o Strategy tem como objetivo ajudar a encapsular e intercambiar livremente classes usando uma interface comum. Isso ajuda a manter um acoplamento fraco entre o cliente e as classes e permite adicionar quantas implementa\u00e7\u00f5es forem necess\u00e1rias.<\/p>\n<p>O padr\u00e3o Strategy \u00e9 conhecido por ser extremamente \u00fatil em situa\u00e7\u00f5es em que a mesma opera\u00e7\u00e3o precisa ser realizada usando m\u00e9todos\/algoritmos diferentes ou quando blocos de switch massivos precisam ser substitu\u00eddos por um c\u00f3digo mais leg\u00edvel.<\/p>\n<p>Aqui est\u00e1 um exemplo do padr\u00e3o Strategy:<\/p>\n<pre><code class=\"language-js\">\/\/ The strategy class that can encapsulate all hosting providers\nfunction HostingProvider() {\n   \/\/ store the provider\n   this.provider = \"\"\n\n   \/\/ set the provider\n   this.setProvider = function(provider) {\n       this.provider = provider\n   }\n\n   \/\/ set the website configuration for which each hosting provider would calculate costs\n   this.setConfiguration = function(configuration) {\n       this.configuration = configuration\n   }\n\n   \/\/ the generic estimate method that calls the provider's unique methods to calculate the costs\n   this.estimateMonthlyCost = function() {\n       return this.provider.estimateMonthlyCost(this.configuration)\n   }\n}\n\n\/\/ Foo Hosting charges for each second and KB of hosting usage\nfunction FooHosting (){\n   this.name = \"FooHosting\"\n   this.rate = 0.0000027\n\n   this.estimateMonthlyCost = function(configuration){\n       return configuration.duration * configuration.workloadSize * this.rate\n   }\n}\n\n\/\/ Bar Hosting charges per minute instead of seconds\nfunction BarHosting (){\n   this.name = \"BarHosting\"\n   this.rate = 0.00018\n\n   this.estimateMonthlyCost = function(configuration){\n       return configuration.duration \/ 60 * configuration.workloadSize * this.rate\n   }\n}\n\n\/\/ Baz Hosting assumes the average workload to be of 10 MB in size\nfunction BazHosting (){\n   this.name = \"BazHosting\"\n   this.rate = 0.032\n\n   this.estimateMonthlyCost = function(configuration){\n       return configuration.duration * this.rate\n   }\n}\n\nfunction run() {\n\n   \/\/ Create a website configuration for a website that is up for 24 hours and takes 10 MB of hosting space\n   let workloadConfiguration = {\n       duration: 84700,\n       workloadSize: 10240\n   }\n\n   \/\/ Create the hosting provider instances\n   let fooHosting = new FooHosting()\n   let barHosting = new BarHosting()\n   let bazHosting = new BazHosting()\n\n   \/\/ Create the instance of the strategy class\n   let hostingProvider = new HostingProvider()\n\n   \/\/ Set the configuration against which the rates have to be calculated\n   hostingProvider.setConfiguration(workloadConfiguration)\n\n   \/\/ Set each provider one by one and print the rates\n   hostingProvider.setProvider(fooHosting)\n   console.log(\"FooHosting cost: \" + hostingProvider.estimateMonthlyCost())\n   \/\/ Output: FooHosting cost: 2341.7856\n\n   hostingProvider.setProvider(barHosting)\n   console.log(\"BarHosting cost: \" + hostingProvider.estimateMonthlyCost())\n   \/\/ Output: BarHosting cost: 2601.9840\n\n   hostingProvider.setProvider(bazHosting)\n   console.log(\"BarHosting cost: \" + hostingProvider.estimateMonthlyCost())\n   \/\/ Output: BarHosting cost: 2710.4000\n\n}\n\nrun()<\/code><\/pre>\n<p>O padr\u00e3o Strategy \u00e9 excelente quando se trata de introduzir novas varia\u00e7\u00f5es de uma entidade sem alterar muito os clientes. No entanto, pode parecer exagerado se voc\u00ea tiver apenas algumas varia\u00e7\u00f5es para implementar.<\/p>\n<p>Al\u00e9m disso, a encapsula\u00e7\u00e3o retira detalhes mais espec\u00edficos sobre a l\u00f3gica interna de cada variante, fazendo com que o cliente n\u00e3o esteja ciente de como uma variante vai se comportar.<\/p>\n<h4>20. Visitor<\/h4>\n<p>O padr\u00e3o Visitor tem como objetivo ajudar a tornar o c\u00f3digo extens\u00edvel.<\/p>\n<p>A ideia \u00e9 fornecer um m\u00e9todo na classe que permite que objetos de outras classes fa\u00e7am altera\u00e7\u00f5es nos objetos da classe atual de maneira f\u00e1cil. Os outros objetos visitam o objeto atual (tamb\u00e9m chamado de objeto local) ou a classe atual aceita os objetos visitantes, e o objeto local lida com a visita de cada objeto externo de maneira apropriada.<\/p>\n<p>Veja como voc\u00ea pode us\u00e1-lo:<\/p>\n<pre><code class=\"language-js\">\/\/ Visitor class that defines the methods to be called when visiting each place\nfunction Reader(name, cash) {\n    this.name = name\n    this.cash = cash\n\n    \/\/ The visit methods can access the place object and invoke available functions\n    this.visitBookstore = function(bookstore) {\n        console.log(this.name + \" visited the bookstore and bought a book\")\n        bookstore.purchaseBook(this)\n    }\n\n    this.visitLibrary = function() {\n        console.log(this.name + \" visited the library and read a book\")\n    }\n\n    \/\/ Helper function to demonstrate a transaction\n    this.pay = function(amount) {\n        this.cash -= amount\n    }\n}\n\n\/\/ Place class for a library\nfunction Library () {\n    this.accept = function(reader) {\n        reader.visitLibrary()\n    }\n}\n\n\/\/ Place class for a bookstore that allows purchasing book\nfunction Bookstore () {\n    this.accept = function(reader) {\n        reader.visitBookstore(this)\n    }\n\n    this.purchaseBook = function (visitor) {\n        console.log(visitor.name + \" bought a book\")\n        visitor.pay(8)\n    }\n}\n\n\nfunction run() {\n    \/\/ Create a reader (the visitor)\n    let reader = new Reader(\"Rick,\" 30)\n\n    \/\/ Create the places\n    let booksInc = new Bookstore()\n    let publicLibrary = new Library()\n\n    \/\/ The reader visits the library\n    publicLibrary.accept(reader)\n    \/\/ Output: Rick visited the library and read a book\n    console.log(reader.name + \" has $\" + reader.cash)\n    \/\/ Output: Rick has $30\n\n    \/\/ The reader visits the bookstore\n    booksInc.accept(reader)\n    \/\/ Output: Rick visited the bookstore and bought a book\n    console.log(reader.name + \" has $\" + reader.cash)\n    \/\/ Output: Rick has $22\n}\n\nrun()<\/code><\/pre>\n<p>A \u00fanica falha neste projeto \u00e9 que cada classe de visitantes precisa ser atualizada sempre que um novo lugar \u00e9 adicionado ou modificado. Nos casos em que v\u00e1rios visitantes e objetos de coloca\u00e7\u00e3o existem juntos, isso pode ser dif\u00edcil de manter.<\/p>\n<p>Fora isso, o m\u00e9todo funciona muito bem para melhorar a funcionalidade das aulas dinamicamente.<\/p>\n<h2>Melhores pr\u00e1ticas para implementar padr\u00f5es de Design<\/h2>\n<p>Agora que voc\u00ea j\u00e1 viu os padr\u00f5es de design mais comuns em JavaScript, aqui est\u00e3o algumas dicas que voc\u00ea deve ter em mente ao implement\u00e1-los.<\/p>\n<h3>Tenha um cuidado especial para entender se um padr\u00e3o se encaixa na solu\u00e7\u00e3o<\/h3>\n<p>Essa dica deve ser aplicada antes de implementar um padr\u00e3o de design em seu c\u00f3digo-fonte. Embora possa parecer que um padr\u00e3o de design \u00e9 a solu\u00e7\u00e3o para todos os seus problemas, reserve um momento para analisar criticamente se isso \u00e9 verdadeiro.<\/p>\n<p>Existem muitos padr\u00f5es que resolvem o mesmo problema, mas seguem abordagens diferentes e t\u00eam consequ\u00eancias diferentes. Portanto, seu crit\u00e9rio para selecionar um padr\u00e3o de design n\u00e3o deve se basear apenas em se ele resolve seu problema ou n\u00e3o, mas tamb\u00e9m em como ele resolve eficientemente seu problema e se h\u00e1 algum outro padr\u00e3o que possa apresentar uma solu\u00e7\u00e3o mais eficiente.<\/p>\n<h3>Entenda os custos da implementa\u00e7\u00e3o de um padr\u00e3o antes de come\u00e7ar<\/h3>\n<p>Compreenda os custos de implementar um padr\u00e3o antes de come\u00e7ar<br \/>\nEmbora os padr\u00f5es de design pare\u00e7am ser a melhor solu\u00e7\u00e3o para todos os <a href=\"https:\/\/kinsta.com\/pt\/blog\/erros-no-javascript\/\">problemas de engenharia<\/a>, voc\u00ea n\u00e3o deve come\u00e7ar a implement\u00e1-los em seu c\u00f3digo-fonte imediatamente.<\/p>\n<p>Ao avaliar as consequ\u00eancias de implementar uma solu\u00e7\u00e3o, voc\u00ea tamb\u00e9m precisa levar em considera\u00e7\u00e3o sua pr\u00f3pria situa\u00e7\u00e3o. Voc\u00ea tem uma equipe grande de desenvolvedores de software que est\u00e3o bem capacitados para entender e manter os padr\u00f5es de design? Ou voc\u00ea \u00e9 um fundador em est\u00e1gio inicial com uma equipe m\u00ednima de desenvolvimento, procurando lan\u00e7ar rapidamente um MVP do seu produto? Se a resposta for sim para a \u00faltima pergunta, os padr\u00f5es de design podem n\u00e3o ser a forma mais ideal de desenvolvimento para voc\u00ea.<\/p>\n<p>Os padr\u00f5es de design n\u00e3o levam a uma grande reutiliza\u00e7\u00e3o de c\u00f3digo, a menos que sejam planejados em um est\u00e1gio muito inicial do design do aplicativo. Usar padr\u00f5es de design aleatoriamente em v\u00e1rias etapas pode levar a uma arquitetura de aplicativo desnecessariamente complexa, que voc\u00ea ter\u00e1 que passar semanas simplificando.<\/p>\n<p>A efic\u00e1cia de um padr\u00e3o de design n\u00e3o pode ser avaliada por meio de testes. \u00c9 a <a href=\"https:\/\/kinsta.com\/pt\/blog\/erros-no-javascript\/\">experi\u00eancia e a introspec\u00e7\u00e3o da sua equipe<\/a> que v\u00e3o lhe dizer se eles funcionam. Somente se voc\u00ea tiver tempo e recursos para alocar para esses aspectos, os padr\u00f5es de design realmente resolver\u00e3o seus problemas.<\/p>\n<h3>N\u00e3o transforme todas as solu\u00e7\u00f5es em padr\u00f5es<\/h3>\n<p>Outra regra a ser lembrada \u00e9 evitar tentar transformar cada par de problema-solu\u00e7\u00e3o em um padr\u00e3o de design e us\u00e1-lo onde voc\u00ea v\u00ea espa\u00e7o para isso.<\/p>\n<p>Embora seja bom identificar solu\u00e7\u00f5es padr\u00e3o e t\u00ea-las em mente ao encontrar problemas semelhantes, existe uma boa chance de que o novo problema que voc\u00ea encontrou n\u00e3o se encaixe na mesma descri\u00e7\u00e3o exata de um problema anterior. Nesse caso, voc\u00ea pode acabar implementando uma solu\u00e7\u00e3o inferior e desperdi\u00e7ando recursos.<\/p>\n<p>Os padr\u00f5es de design s\u00e3o considerados hoje como exemplos principais de pares de problemas-solu\u00e7\u00f5es porque foram testados por centenas e milhares de programadores ao longo do tempo e foram generalizados o m\u00e1ximo poss\u00edvel. Se voc\u00ea tentar replicar esse esfor\u00e7o apenas olhando para um monte de problemas e solu\u00e7\u00f5es e chamando-os de semelhantes, voc\u00ea pode acabar causando muito mais danos ao seu c\u00f3digo do que jamais esperava.<\/p>\n<h2>Quando voc\u00ea deve usar os padr\u00f5es de design?<\/h2>\n<p>Para resumir, aqui est\u00e3o algumas dicas a serem observadas ao usar padr\u00f5es de design. Nem todas se aplicam ao desenvolvimento de todos os aplicativos, mas devem fornecer uma boa ideia do que observar ao pensar em usar padr\u00f5es de design:<\/p>\n<ul>\n<li>Voc\u00ea possui uma equipe interna de desenvolvedores competentes que possui um bom entendimento dos padr\u00f5es de design.<\/li>\n<li>Voc\u00ea est\u00e1 seguindo um modelo de ciclo de vida de desenvolvimento de software (SDLC) que permite discuss\u00f5es aprofundadas sobre a arquitetura do seu aplicativo, e os padr\u00f5es de design surgiram nessas discuss\u00f5es.<\/li>\n<li>O mesmo conjunto de problemas surgiu v\u00e1rias vezes nas discuss\u00f5es de design, e voc\u00ea sabe qual padr\u00e3o de design se encaixar\u00e1 no caso.<\/li>\n<li>Voc\u00ea tentou resolver uma varia\u00e7\u00e3o menor do problema de forma independente com o padr\u00e3o de design.<\/li>\n<li>Com o padr\u00e3o de design implementado, seu c\u00f3digo n\u00e3o parece excessivamente complexo.<\/li>\n<\/ul>\n<p>Se um padr\u00e3o de design resolve o seu problema e ajuda voc\u00ea a escrever c\u00f3digo simples, reutiliz\u00e1vel, modular, com baixo acoplamento e livre de &#8220;code smells&#8221; (sinais de c\u00f3digo problem\u00e1tico), pode ser a abordagem correta a seguir.<\/p>\n<p>Outra dica importante a ser lembrada \u00e9 evitar fazer de tudo sobre os padr\u00f5es de design. Os padr\u00f5es de design t\u00eam como objetivo ajud\u00e1-lo a resolver problemas. Eles n\u00e3o s\u00e3o leis a serem seguidas ou regras a serem rigorosamente seguidas. As regras e leis definitivas ainda s\u00e3o as mesmas: mantenha seu c\u00f3digo limpo, simples, leg\u00edvel e escal\u00e1vel. Se um padr\u00e3o de design ajuda voc\u00ea a fazer isso enquanto resolve o seu problema, voc\u00ea est\u00e1 no caminho certo.<\/p>\n<h2>Resumo<\/h2>\n<p>Os padr\u00f5es de design em JavaScript s\u00e3o uma maneira maravilhosa de abordar problemas enfrentados por v\u00e1rios programadores ao longo do tempo. Eles apresentam solu\u00e7\u00f5es testadas e comprovadas que visam manter sua base de c\u00f3digo limpa e com baixo acoplamento.<\/p>\n<p>Hoje em dia, <a href=\"https:\/\/kinsta.com\/pt\/blog\/erros-no-javascript\/\">existem centenas de padr\u00f5es de design<\/a> dispon\u00edveis que resolvem quase qualquer problema que voc\u00ea encontre ao desenvolver aplicativos. No entanto, nem todos os padr\u00f5es de design realmente resolver\u00e3o seu problema todas as vezes.<br \/>\n<\/p>\n<p>Assim como qualquer outra <a href=\"https:\/\/kinsta.com\/pt\/blog\/melhores-praticas-react\/\">conven\u00e7\u00e3o de programa\u00e7\u00e3o<\/a>, os padr\u00f5es de design devem ser considerados como sugest\u00f5es para resolver problemas. Eles n\u00e3o s\u00e3o leis a serem seguidas o tempo todo, e se voc\u00ea trat\u00e1-los como leis, pode acabar causando muitos danos aos seus aplicativos.<\/p>\n<p>Uma vez que seu aplicativo esteja conclu\u00eddo, voc\u00ea precisar\u00e1 de um lugar para hosped\u00e1-lo &#8211; e as <a href=\"https:\/\/sevalla.com\/application-hosting\/\">solu\u00e7\u00f5es de hospedagem de aplicativos da Kinsta<\/a> est\u00e3o entre as mais r\u00e1pidas, confi\u00e1veis \u200b\u200be seguras. Basta fazer login na sua conta <a href=\"https:\/\/kinsta.com\/pt\/mykinsta\/\">MyKinsta<\/a> (painel administrativo personalizado da Kinsta), conectar-se ao seu <a href=\"https:\/\/kinsta.com\/pt\/blog\/que-github\/\">reposit\u00f3rio do GitHub<\/a> e lan\u00e7ar! Al\u00e9m disso, voc\u00ea paga apenas pelos recursos que seu aplicativo utiliza.<\/p>\n<div class=\"group w-full text-gray-800 dark:text-gray-100 border-b border-black\/10 dark:border-gray-900\/50 bg-gray-50 dark:bg-[#444654]\">\n<div class=\"flex p-4 gap-4 text-base md:gap-6 md:max-w-2xl lg:max-w-[38rem] xl:max-w-3xl md:py-6 lg:px-0 m-auto\">\n<div class=\"relative flex w-[calc(100%-50px)] flex-col gap-1 md:gap-3 lg:w-[calc(100%-115px)]\">\n<div class=\"flex flex-grow flex-col gap-3\">\n<div class=\"min-h-[20px] flex items-start overflow-x-auto whitespace-pre-wrap break-words flex-col gap-4\">\n<div class=\"markdown prose w-full break-words dark:prose-invert dark\">\n<p>Quais s\u00e3o os padr\u00f5es de design que voc\u00ea utiliza regularmente em seu trabalho de programa\u00e7\u00e3o de software? Ou h\u00e1 algum padr\u00e3o que deixamos de mencionar na lista? Deixe-nos saber nos coment\u00e1rios abaixo!<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"flex justify-between lg:block\">\n<div class=\"text-gray-400 flex self-end lg:self-center justify-center mt-2 gap-2 md:gap-3 lg:gap-1 lg:absolute lg:top-0 lg:translate-x-full lg:right-0 lg:mt-0 lg:pl-2 visible\">\n<p>\u00a0<\/p>\n<div class=\"flex gap-1\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Ao construir aplicativos JavaScript, voc\u00ea pode encontrar cen\u00e1rios onde voc\u00ea precisa construir objetos de uma certa forma predefinida ou reutilizar uma classe comum, modificando ou adaptando &#8230;<\/p>\n","protected":false},"author":238,"featured_media":57136,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kinsta_gated_content":false,"_kinsta_gated_content_redirect":"","footnotes":""},"tags":[],"topic":[978],"class_list":["post-57135","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","topic-tutoriais-javascript"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v24.6 (Yoast SEO v24.6) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Um Guia Extensivo de Padr\u00f5es de Design JavaScript<\/title>\n<meta name=\"description\" content=\"Existem muitos padr\u00f5es de design de JavaScript que podem economizar muito tempo e esfor\u00e7o. Aprenda sobre essas solu\u00e7\u00f5es reutiliz\u00e1veis neste artigo.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/\" \/>\n<meta property=\"og:locale\" content=\"pt_PT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Um Guia Extensivo de Padr\u00f5es de Design JavaScript\" \/>\n<meta property=\"og:description\" content=\"Existem muitos padr\u00f5es de design de JavaScript que podem economizar muito tempo e esfor\u00e7o. Aprenda sobre essas solu\u00e7\u00f5es reutiliz\u00e1veis neste artigo.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/\" \/>\n<meta property=\"og:site_name\" content=\"Kinsta\u00ae\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/kinstapt\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-02-14T08:23:29+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-08-22T06:35:35+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/02\/javascript-design-patterns.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1460\" \/>\n\t<meta property=\"og:image:height\" content=\"730\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Kumar Harsh\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:description\" content=\"Existem muitos padr\u00f5es de design de JavaScript que podem economizar muito tempo e esfor\u00e7o. Aprenda sobre essas solu\u00e7\u00f5es reutiliz\u00e1veis neste artigo.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/02\/javascript-design-patterns.png\" \/>\n<meta name=\"twitter:creator\" content=\"@kinsta_pt\" \/>\n<meta name=\"twitter:site\" content=\"@kinsta_pt\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kumar Harsh\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo estimado de leitura\" \/>\n\t<meta name=\"twitter:data2\" content=\"53 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/\"},\"author\":{\"name\":\"Kumar Harsh\",\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9\"},\"headline\":\"Um Guia Extensivo de Padr\u00f5es de Design JavaScript\",\"datePublished\":\"2023-02-14T08:23:29+00:00\",\"dateModified\":\"2023-08-22T06:35:35+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/\"},\"wordCount\":6749,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/pt\/#organization\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/02\/javascript-design-patterns.png\",\"inLanguage\":\"pt-PT\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/\",\"url\":\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/\",\"name\":\"Um Guia Extensivo de Padr\u00f5es de Design JavaScript\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/pt\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/02\/javascript-design-patterns.png\",\"datePublished\":\"2023-02-14T08:23:29+00:00\",\"dateModified\":\"2023-08-22T06:35:35+00:00\",\"description\":\"Existem muitos padr\u00f5es de design de JavaScript que podem economizar muito tempo e esfor\u00e7o. Aprenda sobre essas solu\u00e7\u00f5es reutiliz\u00e1veis neste artigo.\",\"breadcrumb\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#breadcrumb\"},\"inLanguage\":\"pt-PT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-PT\",\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#primaryimage\",\"url\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/02\/javascript-design-patterns.png\",\"contentUrl\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/02\/javascript-design-patterns.png\",\"width\":1460,\"height\":730},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/kinsta.com\/pt\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tutoriais de JavaScript\",\"item\":\"https:\/\/kinsta.com\/pt\/topicos\/tutoriais-javascript\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Um Guia Extensivo de Padr\u00f5es de Design JavaScript\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/kinsta.com\/pt\/#website\",\"url\":\"https:\/\/kinsta.com\/pt\/\",\"name\":\"Kinsta\u00ae\",\"description\":\"Solu\u00e7\u00f5es de hospedagem Premium, r\u00e1pida e segura\",\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/pt\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/kinsta.com\/pt\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-PT\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/kinsta.com\/pt\/#organization\",\"name\":\"Kinsta\",\"url\":\"https:\/\/kinsta.com\/pt\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-PT\",\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/12\/kinsta-logo.jpeg\",\"contentUrl\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/12\/kinsta-logo.jpeg\",\"width\":500,\"height\":500,\"caption\":\"Kinsta\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/kinstapt\/\",\"https:\/\/x.com\/kinsta_pt\",\"https:\/\/www.instagram.com\/kinstahosting\/\",\"https:\/\/www.linkedin.com\/company\/kinsta\/\",\"https:\/\/www.pinterest.com\/kinstahosting\/\",\"https:\/\/www.youtube.com\/c\/Kinsta\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9\",\"name\":\"Kumar Harsh\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-PT\",\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/de2d8d6273bdcc3dfa2f8270428f95b2?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/de2d8d6273bdcc3dfa2f8270428f95b2?s=96&d=mm&r=g\",\"caption\":\"Kumar Harsh\"},\"description\":\"Kumar is a software developer and a technical author based in India. He specializes in JavaScript and DevOps. You can learn more about his work on his website.\",\"sameAs\":[\"https:\/\/kumarharsh.me\"],\"url\":\"https:\/\/kinsta.com\/pt\/blog\/author\/kumarharsh\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Um Guia Extensivo de Padr\u00f5es de Design JavaScript","description":"Existem muitos padr\u00f5es de design de JavaScript que podem economizar muito tempo e esfor\u00e7o. Aprenda sobre essas solu\u00e7\u00f5es reutiliz\u00e1veis neste artigo.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/","og_locale":"pt_PT","og_type":"article","og_title":"Um Guia Extensivo de Padr\u00f5es de Design JavaScript","og_description":"Existem muitos padr\u00f5es de design de JavaScript que podem economizar muito tempo e esfor\u00e7o. Aprenda sobre essas solu\u00e7\u00f5es reutiliz\u00e1veis neste artigo.","og_url":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/","og_site_name":"Kinsta\u00ae","article_publisher":"https:\/\/www.facebook.com\/kinstapt\/","article_published_time":"2023-02-14T08:23:29+00:00","article_modified_time":"2023-08-22T06:35:35+00:00","og_image":[{"width":1460,"height":730,"url":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/02\/javascript-design-patterns.png","type":"image\/png"}],"author":"Kumar Harsh","twitter_card":"summary_large_image","twitter_description":"Existem muitos padr\u00f5es de design de JavaScript que podem economizar muito tempo e esfor\u00e7o. Aprenda sobre essas solu\u00e7\u00f5es reutiliz\u00e1veis neste artigo.","twitter_image":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/02\/javascript-design-patterns.png","twitter_creator":"@kinsta_pt","twitter_site":"@kinsta_pt","twitter_misc":{"Escrito por":"Kumar Harsh","Tempo estimado de leitura":"53 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#article","isPartOf":{"@id":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/"},"author":{"name":"Kumar Harsh","@id":"https:\/\/kinsta.com\/pt\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9"},"headline":"Um Guia Extensivo de Padr\u00f5es de Design JavaScript","datePublished":"2023-02-14T08:23:29+00:00","dateModified":"2023-08-22T06:35:35+00:00","mainEntityOfPage":{"@id":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/"},"wordCount":6749,"commentCount":0,"publisher":{"@id":"https:\/\/kinsta.com\/pt\/#organization"},"image":{"@id":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/02\/javascript-design-patterns.png","inLanguage":"pt-PT","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/","url":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/","name":"Um Guia Extensivo de Padr\u00f5es de Design JavaScript","isPartOf":{"@id":"https:\/\/kinsta.com\/pt\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#primaryimage"},"image":{"@id":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/02\/javascript-design-patterns.png","datePublished":"2023-02-14T08:23:29+00:00","dateModified":"2023-08-22T06:35:35+00:00","description":"Existem muitos padr\u00f5es de design de JavaScript que podem economizar muito tempo e esfor\u00e7o. Aprenda sobre essas solu\u00e7\u00f5es reutiliz\u00e1veis neste artigo.","breadcrumb":{"@id":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#breadcrumb"},"inLanguage":"pt-PT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/"]}]},{"@type":"ImageObject","inLanguage":"pt-PT","@id":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#primaryimage","url":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/02\/javascript-design-patterns.png","contentUrl":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/02\/javascript-design-patterns.png","width":1460,"height":730},{"@type":"BreadcrumbList","@id":"https:\/\/kinsta.com\/pt\/blog\/padroes-de-design-javascript\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/kinsta.com\/pt\/"},{"@type":"ListItem","position":2,"name":"Tutoriais de JavaScript","item":"https:\/\/kinsta.com\/pt\/topicos\/tutoriais-javascript\/"},{"@type":"ListItem","position":3,"name":"Um Guia Extensivo de Padr\u00f5es de Design JavaScript"}]},{"@type":"WebSite","@id":"https:\/\/kinsta.com\/pt\/#website","url":"https:\/\/kinsta.com\/pt\/","name":"Kinsta\u00ae","description":"Solu\u00e7\u00f5es de hospedagem Premium, r\u00e1pida e segura","publisher":{"@id":"https:\/\/kinsta.com\/pt\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kinsta.com\/pt\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-PT"},{"@type":"Organization","@id":"https:\/\/kinsta.com\/pt\/#organization","name":"Kinsta","url":"https:\/\/kinsta.com\/pt\/","logo":{"@type":"ImageObject","inLanguage":"pt-PT","@id":"https:\/\/kinsta.com\/pt\/#\/schema\/logo\/image\/","url":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/12\/kinsta-logo.jpeg","contentUrl":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/12\/kinsta-logo.jpeg","width":500,"height":500,"caption":"Kinsta"},"image":{"@id":"https:\/\/kinsta.com\/pt\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/kinstapt\/","https:\/\/x.com\/kinsta_pt","https:\/\/www.instagram.com\/kinstahosting\/","https:\/\/www.linkedin.com\/company\/kinsta\/","https:\/\/www.pinterest.com\/kinstahosting\/","https:\/\/www.youtube.com\/c\/Kinsta"]},{"@type":"Person","@id":"https:\/\/kinsta.com\/pt\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9","name":"Kumar Harsh","image":{"@type":"ImageObject","inLanguage":"pt-PT","@id":"https:\/\/kinsta.com\/pt\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/de2d8d6273bdcc3dfa2f8270428f95b2?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/de2d8d6273bdcc3dfa2f8270428f95b2?s=96&d=mm&r=g","caption":"Kumar Harsh"},"description":"Kumar is a software developer and a technical author based in India. He specializes in JavaScript and DevOps. You can learn more about his work on his website.","sameAs":["https:\/\/kumarharsh.me"],"url":"https:\/\/kinsta.com\/pt\/blog\/author\/kumarharsh\/"}]}},"acf":[],"_links":{"self":[{"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/posts\/57135","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/users\/238"}],"replies":[{"embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/comments?post=57135"}],"version-history":[{"count":7,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/posts\/57135\/revisions"}],"predecessor-version":[{"id":62425,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/posts\/57135\/revisions\/62425"}],"alternate":[{"embeddable":true,"hreflang":"en","title":"English","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/57135\/translations\/en"},{"embeddable":true,"hreflang":"it","title":"Italian","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/57135\/translations\/it"},{"embeddable":true,"hreflang":"pt","title":"Portuguese","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/57135\/translations\/pt"},{"embeddable":true,"hreflang":"fr","title":"French","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/57135\/translations\/fr"},{"embeddable":true,"hreflang":"de","title":"German","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/57135\/translations\/de"},{"embeddable":true,"hreflang":"ja","title":"Japanese","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/57135\/translations\/jp"},{"embeddable":true,"hreflang":"nl","title":"Dutch","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/57135\/translations\/nl"},{"embeddable":true,"hreflang":"es","title":"Spanish","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/57135\/translations\/es"},{"embeddable":true,"hreflang":"sv","title":"Swedish","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/57135\/translations\/se"},{"embeddable":true,"hreflang":"da","title":"Danish","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/57135\/translations\/dk"},{"href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/57135\/tree"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/media\/57136"}],"wp:attachment":[{"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/media?parent=57135"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/tags?post=57135"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/topic?post=57135"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}