{"id":50033,"date":"2023-02-14T08:33:39","date_gmt":"2023-02-14T08:33:39","guid":{"rendered":"https:\/\/kinqsta.com\/se\/?p=50033&#038;preview=true&#038;preview_id=50033"},"modified":"2023-09-18T10:21:25","modified_gmt":"2023-09-18T10:21:25","slug":"javascript-design-monster","status":"publish","type":"post","link":"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/","title":{"rendered":"En omfattande guide om JavaScript-designm\u00f6nster"},"content":{"rendered":"<p>N\u00e4r du bygger <a href=\"https:\/\/kinqsta.com\/blog\/what-is-javascript\/\">JavaScript<\/a>-applikationer s\u00e5 kan du st\u00f6ta p\u00e5 scenarier d\u00e4r du m\u00e5ste bygga objekt p\u00e5 ett visst, f\u00f6rdefinierat s\u00e4tt. Det kan \u00e4ven h\u00e4nda att du m\u00e5ste \u00e5teranv\u00e4nda en gemensam klass genom att \u00e4ndra eller anpassa den till flera anv\u00e4ndningsomr\u00e5den.<\/p>\n<p>Det \u00e4r naturligtvis inte bekv\u00e4mt att l\u00f6sa dessa problem om och om igen.<\/p>\n<p>Det \u00e4r h\u00e4r som JavaScript-designm\u00f6nster kommer in i bilden.<\/p>\n<p>JavaScript-designm\u00f6nster ger dig ett strukturerat, upprepningsbart s\u00e4tt att ta itu med vanligt f\u00f6rekommande problem vid JavaScript-utveckling.<\/p>\n<p>I den h\u00e4r guiden s\u00e5 tar vi en titt p\u00e5 vad JavaScript-designm\u00f6nster \u00e4r och hur du kan anv\u00e4nda dem i dina JavaScript-appar.<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>Vad \u00e4r ett JavaScript-designm\u00f6nster?<\/h2>\n<p>JavaScript-designm\u00f6nster \u00e4r upprepningsbara malll\u00f6sningar f\u00f6r ofta f\u00f6rekommande problem vid utveckling av JavaScript-appar.<\/p>\n<p>Id\u00e9n \u00e4r enkel: Programmerare \u00f6ver hela v\u00e4rlden har sedan utvecklingens b\u00f6rjan st\u00e4llts inf\u00f6r \u00e5terkommande problem n\u00e4r de <a href=\"https:\/\/kinqsta.com\/se\/blog\/application-utvecklare\/\">utvecklar appar<\/a>. Med tiden s\u00e5 valde vissa utvecklare d\u00e4rf\u00f6r att dokumentera bepr\u00f6vade och testade s\u00e4tt att hantera dessa problem. Som ett resultat s\u00e5 kunde andra utvecklare h\u00e4nvisa till dessa l\u00f6sningar.<\/p>\n<p>Fler och fler utvecklare valde att anv\u00e4nda dessa l\u00f6sningar och ins\u00e5g att de var effektiva n\u00e4r det g\u00e4llde att l\u00f6sa problemen. De blev d\u00e4rmed accepterade som ett standardiserat s\u00e4tt att l\u00f6sa problem och fick namnet &#8221;designm\u00f6nster&#8221;<\/p>\n<p>I takt med att betydelsen av designm\u00f6nster blev b\u00e4ttre f\u00f6rst\u00e5dd s\u00e5 utvecklades och standardiserades dessa ytterligare. De flesta moderna designm\u00f6nster har numera en definierad struktur och \u00e4r organiserade i flera kategorier. De undervisas dessutom i datavetenskapsrelaterade utbildningar som frist\u00e5ende \u00e4mnen.<\/p>\n<h2>Typer av JavaScript-designm\u00f6nster<\/h2>\n<p>H\u00e4r \u00e4r n\u00e5gra av de mest popul\u00e4ra klassificeringarna av JavaScript-designm\u00f6nster.<\/p>\n<h3>Skapande<\/h3>\n<p>Kreativa designm\u00f6nster \u00e4r s\u00e5dana som hj\u00e4lper till att l\u00f6sa problem kring skapande och hantering av nya objektinstanser i JavaScript. Det kan vara s\u00e5 enkelt som att begr\u00e4nsa en klass till att bara ha ett objekt.\u00a0 Processen kan dock \u00e4ven vara s\u00e5 komplex som att definiera en intrikat metod f\u00f6r att handplocka och l\u00e4gga till varje funktion i ett JavaScript-objekt.<\/p>\n<p>N\u00e5gra exempel p\u00e5 skapande designm\u00f6nster \u00e4r bland annat Singleton, Factory, Abstract Factory och Builder.<\/p>\n<h3>Strukturellt<\/h3>\n<p>Strukturella designm\u00f6nster \u00e4r s\u00e5dana som hj\u00e4lper till att l\u00f6sa problem kring hantering av JavaScript-objektens struktur (eller schema). Dessa problem kan vara att skapa en relation mellan tv\u00e5 olika objekt eller att abstrahera vissa funktioner i ett objekt f\u00f6r specifika anv\u00e4ndare.<\/p>\n<p>N\u00e5gra exempel p\u00e5 strukturella designm\u00f6nster \u00e4r Adapter, Bridge, Composite och Facade.<\/p>\n<h3>Beteendem\u00f6nster<\/h3>\n<p>Beteendem\u00e4ssiga designm\u00f6nster \u00e4r s\u00e5dana som hj\u00e4lper till att l\u00f6sa problem med hur kontroll (och ansvar) \u00f6verf\u00f6rs mellan olika objekt. Dessa problem kan handla om att kontrollera \u00e5tkomsten till en l\u00e4nkad lista eller att skapa en enda enhet som kan kontrollera \u00e5tkomsten till flera typer av objekt.<\/p>\n<p>N\u00e5gra exempel p\u00e5 beteendem\u00f6nster \u00e4r Command, Iterator, Memento och Observer.<\/p>\n<h3>Samtidighet<\/h3>\n<p>Designm\u00f6nster f\u00f6r samtidighet \u00e4r s\u00e5dana som hj\u00e4lper till att l\u00f6sa problem som r\u00f6r flertr\u00e5dning och multitasking. Dessa problem kan inneb\u00e4ra att man m\u00e5ste beh\u00e5lla ett aktivt objekt bland flera tillg\u00e4ngliga objekt. Det kan \u00e4ven h\u00e4nda att man m\u00e5ste hantera flera h\u00e4ndelser som levereras till ett system genom att dela upp en inkommande inmatning och hantera den bit f\u00f6r bit.<\/p>\n<p>N\u00e5gra exempel p\u00e5 designm\u00f6nster f\u00f6r samtidighet \u00e4r Active Object, Core Reactor och Scheduler.<\/p>\n<h3>Arkitektonisk<\/h3>\n<p>Arkitektoniska designm\u00f6nster \u00e4r s\u00e5dana som hj\u00e4lper till att l\u00f6sa problem med <a href=\"https:\/\/kinqsta.com\/se\/blog\/webb-applikations-arkitektur\/\">programvarudesign<\/a> i bred bem\u00e4rkelse. Dessa \u00e4r i allm\u00e4nhet relaterade till hur man utformar sitt system och s\u00e4kerst\u00e4ller h\u00f6g tillg\u00e4nglighet, begr\u00e4nsar risker och <a href=\"https:\/\/kinqsta.com\/se\/blog\/applikationsprestandaovervakning\/\">undviker flaskhalsar i prestanda<\/a>.<\/p>\n<p>Tv\u00e5 exempel p\u00e5 arkitektoniska designm\u00f6nster \u00e4r MVC och MVVM.<\/p>\n<h2>Element i ett designm\u00f6nster<\/h2>\n<p>N\u00e4stan alla designm\u00f6nster kan delas upp i en upps\u00e4ttning av fyra viktiga komponenter. Dessa \u00e4r:<\/p>\n<ul>\n<li><strong>M\u00f6nsternamn<\/strong>: Detta anv\u00e4nds f\u00f6r att identifiera ett designm\u00f6nster n\u00e4r man kommunicerar med andra anv\u00e4ndare. M\u00f6nsternamn \u00e4r exempelvis &#8221;singleton&#8221;, &#8221;prototyp&#8221; med flera.<\/li>\n<li><strong>Problem<\/strong>: H\u00e4r beskrivs syftet med designm\u00f6nstret. Det \u00e4r en liten beskrivning av det problem som designm\u00f6nstret f\u00f6rs\u00f6ker l\u00f6sa. Det kan \u00e4ven inkludera ett exempelscenario f\u00f6r att b\u00e4ttre f\u00f6rklara problemet. Ut\u00f6ver detta s\u00e5 kan det dessutom inneh\u00e5lla en lista \u00f6ver villkor som m\u00e5ste uppfyllas f\u00f6r att ett designm\u00f6nster ska l\u00f6sa det underliggande problemet fullt ut.<\/li>\n<li><strong>L\u00f6sning<\/strong>: Detta \u00e4r l\u00f6sningen p\u00e5 det aktuella problemet, som best\u00e5r av element som klasser, metoder, gr\u00e4nssnitt osv. Det \u00e4r h\u00e4r som huvuddelen av ett designm\u00f6nster ligger &#8211; det inneh\u00e5ller relationer, ansvar och samarbetspartners f\u00f6r olika element som \u00e4r tydligt definierade.<\/li>\n<li><strong>Resultat<\/strong>: Detta \u00e4r en analys av hur v\u00e4l m\u00f6nstret kunde l\u00f6sa problemet. Saker som utrymmes- och tidsanv\u00e4ndning diskuteras, tillsammans med alternativa tillv\u00e4gag\u00e5ngss\u00e4tt f\u00f6r att l\u00f6sa samma problem.<\/li>\n<\/ul>\n<p>Om du vill l\u00e4ra dig mer om designm\u00f6nster och deras tillkomst s\u00e5 har MSU ett <a href=\"https:\/\/www.cse.msu.edu\/~cse870\/Lectures\/SS2005\/08-design-patterns.ppt\">kortfattat studiematerial<\/a> som du kan anv\u00e4nda.<\/p>\n<h2>Varf\u00f6r ska du anv\u00e4nda designm\u00f6nster?<\/h2>\n<p>Det finns flera anledningar till varf\u00f6r du b\u00f6r anv\u00e4nda designm\u00f6nster:<\/p>\n<ul>\n<li><strong>De \u00e4r bepr\u00f6vade och testade<\/strong>: Med ett designm\u00f6nster s\u00e5 har du en bepr\u00f6vad och testad l\u00f6sning p\u00e5 ditt problem (s\u00e5 l\u00e4nge som designm\u00f6nstret passar in p\u00e5 beskrivningen av ditt problem). Du beh\u00f6ver inte sl\u00f6sa tid p\u00e5 att leta efter alternativa l\u00f6sningar, och du kan vara s\u00e4ker p\u00e5 att du har en l\u00f6sning som tar hand om grundl\u00e4ggande prestandaoptimering \u00e5t dig.<\/li>\n<li><strong>De \u00e4r l\u00e4tta att f\u00f6rst\u00e5<\/strong>: Designm\u00f6nster \u00e4r avsedda att vara sm\u00e5, enkla och l\u00e4tta att f\u00f6rst\u00e5. Du beh\u00f6ver d\u00e4rf\u00f6r inte vara en specialiserad programmerare som har arbetat i en specifik bransch i \u00e5rtionden f\u00f6r att f\u00f6rst\u00e5 vilket designm\u00f6nster som du ska anv\u00e4nda. De \u00e4r medvetet generiska (inte begr\u00e4nsade till n\u00e5got s\u00e4rskilt programmeringsspr\u00e5k). Som ett resultat s\u00e5 kan de f\u00f6rst\u00e5s av alla som har tillr\u00e4ckliga probleml\u00f6sningsf\u00f6rm\u00e5gor. Detta underl\u00e4ttar \u00e4ven n\u00e4r du har ett byte av \u00e4gare i ditt tekniska team: En kod som bygger p\u00e5 ett designm\u00f6nster \u00e4r l\u00e4ttare att f\u00f6rst\u00e5 f\u00f6r en ny programvaruutvecklare.<\/li>\n<\/ul>\n<ul>\n<li><strong>De \u00e4r enkla att implementera<\/strong>: De flesta designm\u00f6nster \u00e4r mycket enkla, vilket du kommer att se senare i v\u00e5r artikel. Du beh\u00f6ver inte k\u00e4nna till flera <a href=\"https:\/\/kinqsta.com\/se\/blog\/pythons-objektorienterade-programmering\/\">programmeringskoncept<\/a> f\u00f6r att implementera dem i din kod.<\/li>\n<\/ul>\n<ul>\n<li><strong>De f\u00f6resl\u00e5r en kodarkitektur som l\u00e4tt kan \u00e5teranv\u00e4ndas<\/strong>: \u00c5teranv\u00e4ndbarhet och <a href=\"https:\/\/kinqsta.com\/blog\/html-best-practices\/\">renhet<\/a> i koden <a href=\"https:\/\/kinqsta.com\/blog\/html-best-practices\/\">uppmuntras starkt<\/a> i hela teknikbranschen. Designm\u00f6nster kan hj\u00e4lpa dig att uppn\u00e5 detta. Dessa m\u00f6nster \u00e4r ett standardiserat s\u00e4tt att l\u00f6sa problem. D\u00e4rf\u00f6r s\u00e5 har deras designers sett till att den omslutande apparkitekturen f\u00f6rblir \u00e5teranv\u00e4ndbar, flexibel och kompatibel med de flesta former av kodskrivning.<\/li>\n<\/ul>\n<ul>\n<li><strong>De sparar tid och sparar appstorlek<\/strong>: En av de st\u00f6rsta f\u00f6rdelarna med att f\u00f6rlita sig p\u00e5 en standard-upps\u00e4ttning av l\u00f6sningar \u00e4r att de hj\u00e4lper dig att spara tid n\u00e4r du implementerar dem. Det finns en god chans att hela ditt utvecklingsteam k\u00e4nner till designm\u00f6nster v\u00e4l. Som ett resultat s\u00e5 blir det l\u00e4ttare f\u00f6r dem att <a href=\"https:\/\/kinqsta.com\/se\/blog\/microsoft-teams-vs-slack\/\">planera, kommunicera och samarbeta<\/a> n\u00e4r de implementerar dem. Bepr\u00f6vade och testade l\u00f6sningar inneb\u00e4r att det finns en god chans att ni inte kommer att l\u00e4cka n\u00e5gra resurser eller ta en omv\u00e4g n\u00e4r ni bygger n\u00e5gon funktion. Detta sparar b\u00e5de tid och utrymme. Dessutom s\u00e5 erbjuder de flesta <a href=\"https:\/\/kinqsta.com\/se\/blog\/basta-programmeringsspraket-att-lara-sig\/\">programmeringsspr\u00e5ken<\/a> standardmallbibliotek som redan implementerar n\u00e5gra vanliga designm\u00f6nster som Iterator och Observer.<\/li>\n<\/ul>\n<h2>De 20 b\u00e4sta designm\u00f6nstren f\u00f6r JavaScript som du b\u00f6r beh\u00e4rska<\/h2>\n<p>Nu f\u00f6rst\u00e5r du vad ett designm\u00f6nster best\u00e5r av och varf\u00f6r du beh\u00f6ver dem. Det \u00e4r dags att djupdyka i hur n\u00e5gra av de vanligaste JavaScript-designm\u00f6nstren kan implementeras i en <a href=\"https:\/\/kinqsta.com\/se\/blog\/node-js-appar\/\">JavaScript-app<\/a>.<\/p>\n<h3>Skapande<\/h3>\n<p>L\u00e5t oss b\u00f6rja diskussionen med n\u00e5gra grundl\u00e4ggande, l\u00e4ttl\u00e4rda kreativa designm\u00f6nster.<\/p>\n<h4>1. Singleton<\/h4>\n<p>Singleton-m\u00f6nstret \u00e4r ett av de mest anv\u00e4nda designm\u00f6nstren i hela mjukvaruutvecklingsbranschen. Det problem som det syftar till att l\u00f6sa \u00e4r att endast uppr\u00e4tth\u00e5lla en enda instans av en klass. Detta kan exempelvis vara praktiskt n\u00e4r man instansierar objekt som \u00e4r resurskr\u00e4vande, t.ex. databashanterare.<\/p>\n<p>S\u00e5 h\u00e4r kan du implementera detta i 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>Singleton-m\u00f6nstret \u00e4r k\u00e4nt f\u00f6r att f\u00f6rsv\u00e5ra fels\u00f6kning eftersom det maskerar beroenden och kontrollerar \u00e5tkomsten till initialisering eller f\u00f6rst\u00f6ring av en klassinstans.<\/p>\n<h4>2. Factory<\/h4>\n<p>Factory-metoden \u00e4r ocks\u00e5 ett av de mest popul\u00e4ra designm\u00f6nstren. Det problem som Factory-metoden syftar till att l\u00f6sa \u00e4r att skapa objekt utan att anv\u00e4nda den konventionella konstrukt\u00f6ren. Den tar ist\u00e4llet in konfigurationen (eller beskrivningen) av det objekt som du vill ha och returnerar det nyskapade objektet.<\/p>\n<p>S\u00e5 h\u00e4r kan du implementera den i 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>Factory-designm\u00f6nstret styr hur objekten ska skapas och ger dig ett snabbt s\u00e4tt att skapa nya objekt. Du f\u00e5r dessutom ett enhetligt gr\u00e4nssnitt som definierar de egenskaper som dina objekt ska ha. Det g\u00e5r att l\u00e4gga till hur m\u00e5nga hundraser som helst. S\u00e5 l\u00e4nge som metoderna och egenskaperna som rastyperna exponerar f\u00f6rblir desamma kommer de att fungera felfritt \u00e4nd\u00e5.<\/p>\n<p>Observera dock att Factory-m\u00f6nstret ofta kan leda till ett stort antal klasser som kan vara sv\u00e5ra att hantera.<\/p>\n<h4>3. Abstract Factory<\/h4>\n<p>Metoden Abstract Factory tar upp Factory-metoden en niv\u00e5 genom att g\u00f6ra factories abstrakta och d\u00e4rmed utbytbara. Detta sker utan att den anropande milj\u00f6n k\u00e4nner till exakt vilken factory som anv\u00e4nds eller hur den fungerar internt. Den anropande milj\u00f6n vet bara att alla factories har en upps\u00e4ttning gemensamma metoder som den kan anropa f\u00f6r att utf\u00f6ra instans-\u00e5tg\u00e4rden.<\/p>\n<p>S\u00e5 h\u00e4r kan detta genomf\u00f6ras med hj\u00e4lp av det tidigare exemplet:<\/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>Abstract Factory-m\u00f6nstret g\u00f6r det enkelt f\u00f6r dig att utbyta konkreta factories. Det bidrar dessutom till att fr\u00e4mja enhetlighet mellan factories och de produkter som skapas. Det kan dock bli sv\u00e5rt att inf\u00f6ra nya typer av produkter eftersom du m\u00e5ste g\u00f6ra \u00e4ndringar i flera klasser f\u00f6r att f\u00e5 plats med nya metoder\/egenskaper.<\/p>\n<h4>4. Builder<\/h4>\n<p>Builder-m\u00f6nstret \u00e4r ett av de mest komplexa men flexibla skapande JavaScript-designm\u00f6nstren. Det l\u00e5ter dig bygga in varje funktion i din produkt en efter en. Som ett resultat s\u00e5 f\u00e5r du full kontroll \u00f6ver hur ditt objekt byggs samtidigt som du abstraherar bort de interna detaljerna.<\/p>\n<p>I det invecklade exemplet nedan s\u00e5 ser du Builder-designm\u00f6nstret i aktion tillsammans med Director som hj\u00e4lper dig att g\u00f6ra pizzor!<\/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>Du kan koppla ihop Builder med en Director, vilket visas av klassen <code>PizzaShop<\/code> i exemplet ovan. Som ett resultat s\u00e5 kan du definiera en upps\u00e4ttning steg som ska f\u00f6ljas i f\u00f6rv\u00e4g varje g\u00e5ng som du bygger en standardvariant av din produkt. I detta fallet s\u00e5 g\u00e4ller det ett specifikt recept f\u00f6r dina pizzor.<\/p>\n<p>Det enda problemet med det h\u00e4r designm\u00f6nstret \u00e4r att det \u00e4r ganska komplicerat att inr\u00e4tta och underh\u00e5lla. Att l\u00e4gga till nya funktioner p\u00e5 detta s\u00e4tt \u00e4r dock enklare \u00e4n Factory-metoden.<\/p>\n<h4>5. Prototyp<\/h4>\n<p>Designm\u00f6nstret Prototype \u00e4r ett snabbt och enkelt s\u00e4tt att skapa nya objekt fr\u00e5n befintliga objekt genom att klona dem.<\/p>\n<p>F\u00f6rst s\u00e5 skapas ett prototyp-objekt som kan klonas flera g\u00e5nger f\u00f6r att skapa nya objekt. Det \u00e4r praktiskt n\u00e4r det \u00e4r mer resurskr\u00e4vande att direkt instansiera ett objekt \u00e4n att skapa en kopia av ett befintligt objekt.<\/p>\n<p>I exemplet nedan s\u00e5 ser du hur du kan anv\u00e4nda prototype-m\u00f6nstret f\u00f6r att skapa nya dokument baserat p\u00e5 ett inst\u00e4llt malldokument:<\/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>Prototype-metoden fungerar utm\u00e4rkt i fall d\u00e4r en stor del av dina objekt delar samma v\u00e4rden. Den \u00e4r \u00e4ven l\u00e4mplig n\u00e4r det \u00e4r ganska kostsamt att skapa ett nytt objekt helt och h\u00e5llet. Det k\u00e4nns dock som en \u00f6verdrift i de fall d\u00e4r du inte beh\u00f6ver mer \u00e4n n\u00e5gra f\u00e5 instanser av klassen.<\/p>\n<h3>Strukturellt<\/h3>\n<p>Strukturella designm\u00f6nster hj\u00e4lper dig att organisera din aff\u00e4rslogik genom att tillhandah\u00e5lla bepr\u00f6vade s\u00e4tt att strukturera dina klasser. Det finns en m\u00e4ngd olika strukturella designm\u00f6nster som alla tillgodoser unika anv\u00e4ndningsomr\u00e5den.<\/p>\n<h4>6. Adapter<\/h4>\n<p>Ett vanligt problem n\u00e4r man bygger appar \u00e4r att till\u00e5ta samarbete mellan inkompatibla klasser.<\/p>\n<p>Ett bra exempel f\u00f6r att f\u00f6rst\u00e5 detta \u00e4r att bibeh\u00e5lla bak\u00e5tkompatibilitet. Om du skriver en ny version av en klass s\u00e5 vill du naturligtvis att den ska vara l\u00e4tt att anv\u00e4nda p\u00e5 alla st\u00e4llen d\u00e4r den gamla versionen fungerade. Men det kan ju h\u00e4nda att du g\u00f6r brytande \u00e4ndringar som att ta bort eller uppdatera metoder som var avg\u00f6rande f\u00f6r att den gamla versionen skulle fungera. D\u00e5 kan det h\u00e4nda att du f\u00e5r en klass som kr\u00e4ver att alla dess klienter uppdateras f\u00f6r att kunna k\u00f6ras.<\/p>\n<p>I s\u00e5dana fall kan designm\u00f6nstret Adapter hj\u00e4lpa till.<\/p>\n<p>Designm\u00f6nstret Adapter ger dig en abstraktion som \u00f6verbryggar klyftan mellan den nya klassens metoder och egenskaper och den gamla klassens metoder och egenskaper. Det har samma gr\u00e4nssnitt som den gamla klassen, men inkluderar logik f\u00f6r att mappa gamla metoder till de nya metoderna. Som ett resultat s\u00e5 kan det utf\u00f6ras liknande operationer. Detta liknar det s\u00e4tt p\u00e5 vilket ett eluttag fungerar som en adapter mellan en amerikansk kontakt och en europeisk kontakt.<\/p>\n<p>H\u00e4r \u00e4r ett exempel:<\/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>Det st\u00f6rsta problemet med detta designm\u00f6nster \u00e4r att det g\u00f6r k\u00e4llkoden mer komplex. Du beh\u00f6vde redan underh\u00e5lla tv\u00e5 olika klasser, och nu har du ytterligare en klass &#8211; Adapter &#8211; att underh\u00e5lla.<\/p>\n<h4>7. Bridge<\/h4>\n<p>Med Bridge-m\u00f6nstret, som \u00e4r en vidareutveckling av Adapter-m\u00f6nstret, s\u00e5 f\u00e5r b\u00e5de klassen och klienten separata gr\u00e4nssnitt. Som ett resultat s\u00e5 kan b\u00e5da fungera \u00e4ven om de har inkompatibla ursprungliga gr\u00e4nssnitt.<\/p>\n<p>Detta hj\u00e4lper till att utveckla ett mycket l\u00f6st kopplat gr\u00e4nssnitt mellan de tv\u00e5 typerna av objekt. Som ett resultat s\u00e5 f\u00f6rb\u00e4ttras \u00e4ven gr\u00e4nssnittens och deras implementeringars utbyggbarhet f\u00f6r maximal flexibilitet.<\/p>\n<p>S\u00e5 h\u00e4r kan du anv\u00e4nda detta:<\/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>Du kanske redan har gissat att Bridge-m\u00f6nstret \u00f6kar komplexiteten i kodbasen. Dessutom s\u00e5 slutar de flesta gr\u00e4nssnitt vanligtvis med endast en implementering i verkliga anv\u00e4ndningsomr\u00e5den. Du drar med andra ord inte s\u00e5 mycket nytta av \u00e5teranv\u00e4ndbarheten av koden.<\/p>\n<h4>8. Composite<\/h4>\n<p>Designm\u00f6nstret Composite hj\u00e4lper dig att enkelt strukturera och hantera liknande objekt och enheter. Den grundl\u00e4ggande id\u00e9n bakom Composite-m\u00f6nstret \u00e4r att objekten och deras logiska containers kan representeras med hj\u00e4lp av en enda abstrakt klass (som kan lagra data\/metoder som \u00e4r relaterade till objektet och referenser till sig sj\u00e4lv f\u00f6r containern).<\/p>\n<p>Det \u00e4r mest meningsfullt att anv\u00e4nda Composite-m\u00f6nstret n\u00e4r din datamodell liknar en tr\u00e4dstruktur. Du b\u00f6r dock inte f\u00f6rs\u00f6ka att f\u00f6rvandla en datamodell utan tr\u00e4d till en tr\u00e4dliknande datamodell bara f\u00f6r att kunna anv\u00e4nda Composite-m\u00f6nstret. Detta kan n\u00e4mligen ofta ta bort en hel del flexibilitet.<\/p>\n<p>I exemplet nedan s\u00e5 ser du hur du kan anv\u00e4nda designm\u00f6nstret Composite f\u00f6r att konstruera ett f\u00f6rpackningssystem f\u00f6r e-handelsprodukter. Det kan \u00e4ven kan ber\u00e4kna det totala orderv\u00e4rdet per paket:<\/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>Den st\u00f6rsta nackdelen med att anv\u00e4nda Composite-m\u00f6nstret \u00e4r att \u00e4ndringar av komponenternas gr\u00e4nssnitt kan bli mycket sv\u00e5ra i framtiden. Att utforma gr\u00e4nssnitten tar tid och kraft, och datamodellens tr\u00e4dliknande karakt\u00e4r kan g\u00f6ra det mycket sv\u00e5rt att g\u00f6ra de \u00e4ndringar som du vill.<\/p>\n<h4>9. Decorator<\/h4>\n<p>Decorator-m\u00f6nstret hj\u00e4lper dig att l\u00e4gga till nya funktioner till befintliga objekt. Du sveper helt enkelt in dem i ett nytt objekt. Detta liknar det s\u00e4tt p\u00e5 vilket du kan sl\u00e5 in en redan inslagen presentf\u00f6rpackning med nytt omslagspapper hur m\u00e5nga g\u00e5nger som du vill: Varje omslag ger dig m\u00f6jlighet att l\u00e4gga till s\u00e5 m\u00e5nga funktioner som du vill, s\u00e5 det \u00e4r bra n\u00e4r det g\u00e4ller flexibilitet.<\/p>\n<p>Ur ett tekniskt perspektiv s\u00e5 \u00e4r inget arv inblandat. Som ett resultat s\u00e5 f\u00e5r du st\u00f6rre frihet n\u00e4r du utformar aff\u00e4rslogik.<\/p>\n<p>I exemplet nedan s\u00e5 ser du hur Decorator-m\u00f6nstret hj\u00e4lper dig att l\u00e4gga till fler funktioner till en standardklass <code>Customer<\/code>:<\/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>Nackdelarna med det h\u00e4r m\u00f6nstret \u00e4r bland annat att koden \u00e4r mycket komplex. Det finns n\u00e4mligen inte n\u00e5got standardm\u00f6nster f\u00f6r att l\u00e4gga till nya funktioner med hj\u00e4lp av Decorator. Det kan h\u00e4nda att du i slutet av din mjukvaruutvecklings-livscykel f\u00e5r m\u00e5nga oenhetliga och\/eller liknande Decorators.<\/p>\n<p>Om du inte \u00e4r f\u00f6rsiktig n\u00e4r du utformar Decorators s\u00e5 kan det sluta med att du utformar vissa s\u00e5dana s\u00e5 att de \u00e4r logiskt beroende av andra. Om detta inte blir l\u00f6st s\u00e5 kan borttagning eller omstrukturering av Decorators senare i processen orsaka f\u00f6r\u00f6delse f\u00f6r stabiliteten i din applikation.<\/p>\n<h4>10. Facade<\/h4>\n<p>N\u00e4r man bygger de flesta verkliga till\u00e4mpningar s\u00e5 blir aff\u00e4rslogiken oftast ganska komplex n\u00e4r man \u00e4r klar. Det kan h\u00e4nda att flera objekt och metoder \u00e4r inblandade i utf\u00f6randet av k\u00e4rnverksamheten i din applikation. Att h\u00e5lla reda p\u00e5 deras initialiseringar, beroenden, den korrekta ordningen f\u00f6r utf\u00f6randet av metoder osv. kan vara ganska knepigt om det inte g\u00f6rs p\u00e5 r\u00e4tt s\u00e4tt.<\/p>\n<p>Designm\u00f6nstret Facade hj\u00e4lper dig att skapa en abstraktion mellan den milj\u00f6 som \u00e5beropar de ovan n\u00e4mnda operationerna och de objekt och metoder som \u00e4r involverade i utf\u00f6randet av dessa operationer. Denna abstraktion inneh\u00e5ller logiken f\u00f6r initialisering av objekten, sp\u00e5rning av deras beroenden och andra viktiga aktiviteter. Den anropande milj\u00f6n har ingen information om hur en operation utf\u00f6rs. Som ett resultat s\u00e5 kan du fritt uppdatera logiken utan att g\u00f6ra n\u00e5gra brytande \u00e4ndringar i den anropande klienten.<\/p>\n<p>S\u00e5 h\u00e4r kan du anv\u00e4nda detta i en applikation:<\/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>En nackdel med att anv\u00e4nda facade-m\u00f6nstret \u00e4r att det l\u00e4gger till ytterligare ett abstraktionslager mellan aff\u00e4rslogiken och klienten. Det kr\u00e4ver d\u00e4rf\u00f6r ytterligare underh\u00e5ll. Detta \u00f6kar ofta den totala komplexiteten i kodbasen.<\/p>\n<p>Dessutom s\u00e5 blir klassen <code>Facade<\/code> ett obligatoriskt beroende f\u00f6r att appen ska fungera. Som ett resultat s\u00e5 p\u00e5verkar eventuella fel i klassen <code>Facade<\/code> appens funktion direkt.<\/p>\n<h4>11. Flyweight<\/h4>\n<p>Flyweight-m\u00f6nstret hj\u00e4lper dig att l\u00f6sa problem som involverar objekt med \u00e5terkommande komponenter p\u00e5 ett minneseffektivt s\u00e4tt. Det hj\u00e4lper dig helt enkelt att \u00e5teranv\u00e4nda de gemensamma komponenterna i din objekt-pool. Som ett resultat s\u00e5 kan du minska belastningen p\u00e5 minnet och \u00e4ven f\u00e5 snabbare exekveringstider.<\/p>\n<p>I exemplet nedan s\u00e5 lagras en stor mening i minnet med hj\u00e4lp av designm\u00f6nstret Flyweight. Ist\u00e4llet f\u00f6r att lagra varje tecken n\u00e4r det uppst\u00e5r s\u00e5 identifierar applikationen upps\u00e4ttningen av distinkta tecken som har anv\u00e4nts f\u00f6r att skriva stycket och deras typer (nummer eller alfabet). Den bygger sedan \u00e5teranv\u00e4ndbara Flyweights f\u00f6r varje tecken som inneh\u00e5ller detaljer om vilket tecken och vilken typ som lagras.<\/p>\n<p>Huvudmatrisen lagrar sedan bara en lista med referenser till dessa flyweights i den ordning som de f\u00f6rekommer i meningen. D\u00e5 slipper applikationen lagra en instans av teckenobjektet varje g\u00e5ng som det f\u00f6rekommer.<\/p>\n<p>Detta minskar det minne som meningen tar i anspr\u00e5k med h\u00e4lften. T\u00e4nk p\u00e5 att detta \u00e4r en mycket grundl\u00e4ggande f\u00f6rklaring av hur textprocessorer lagrar text.<\/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>Som du kanske redan har m\u00e4rkt s\u00e5 \u00f6kar Flyweight-m\u00f6nstret komplexiteten i din programvarudesign genom att det inte \u00e4r s\u00e4rskilt intuitivt. Om sparande av minne inte \u00e4r ett akut problem f\u00f6r din app s\u00e5 kan Flyweight-m\u00f6nstrets extra komplexitet med andra ord g\u00f6ra mer skada \u00e4n nytta.<\/p>\n<p>Dessutom s\u00e5 byter Flyweight minnet mot bearbetnings-effektivitet. Om du har ont om CPU-cykler s\u00e5 \u00e4r Flyweight d\u00e4rf\u00f6r ingen bra l\u00f6sning f\u00f6r dig.<\/p>\n<h4>12. Proxy<\/h4>\n<p>Proxy-m\u00f6nstret hj\u00e4lper dig att ers\u00e4tta ett objekt med ett annat objekt. Med andra ord s\u00e5 kan proxy-objekt ers\u00e4tta faktiska objekt (som de \u00e4r en proxy av) och kontrollera \u00e5tkomsten till objektet. Dessa proxy-objekt kan anv\u00e4ndas f\u00f6r att utf\u00f6ra vissa \u00e5tg\u00e4rder f\u00f6re eller efter att en anrops-beg\u00e4ran skickas vidare till det faktiska objektet.<\/p>\n<p>I exemplet nedan s\u00e5 ser du hur \u00e5tkomsten till en databasinstans styrs via en proxy som utf\u00f6r n\u00e5gra grundl\u00e4ggande valideringskontroller av beg\u00e4randena innan de till\u00e5ts g\u00e5 igenom:<\/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>Det h\u00e4r designm\u00f6nstret \u00e4r vanligt f\u00f6rekommande i hela branschen och hj\u00e4lper till att enkelt genomf\u00f6ra \u00e5tg\u00e4rder f\u00f6re och efter utf\u00f6randet. Men precis som alla andra designm\u00f6nster s\u00e5 \u00f6kar det \u00e4ven komplexiteten i din kodbas. Undvik d\u00e4rf\u00f6r att anv\u00e4nda det om du inte verkligen beh\u00f6ver det.<\/p>\n<p>Du b\u00f6r \u00e4ven t\u00e4nka p\u00e5 att ytterligare ett objekt \u00e4r involverat n\u00e4r du g\u00f6r anrop till ditt faktiska objekt. Som ett resultat s\u00e5 kan det uppst\u00e5 en viss latens p\u00e5 grund av de extra bearbetnings-operationerna. Optimering av ditt huvudobjekts prestanda inneb\u00e4r nu \u00e4ven att optimera din proxys metoder f\u00f6r prestanda.<\/p>\n<h3>Beteende<\/h3>\n<p>Beteendem\u00e4ssiga designm\u00f6nster hj\u00e4lper dig att l\u00f6sa problem kring hur objekt interagerar med varandra. Det kan handla om att dela eller \u00f6verl\u00e4mna ansvar\/kontroll mellan objekt f\u00f6r att slutf\u00f6ra inst\u00e4llda operationer. Det kan dessutom handla om att \u00f6verf\u00f6ra\/dela data mellan flera objekt p\u00e5 ett s\u00e5 effektivt s\u00e4tt som m\u00f6jligt.<\/p>\n<h4>13. Chain of Responsibility<\/h4>\n<p>Chain of Responsibility-m\u00f6nstret \u00e4r ett av de enklaste beteendedesign-m\u00f6nstren. Det \u00e4r praktiskt n\u00e4r du utformar logik f\u00f6r operationer som kan hanteras av flera handl\u00e4ggare.<\/p>\n<p>I likhet med hur problemtrappning fungerar i supportteam s\u00e5 skickas kontrollen genom en kedja av handl\u00e4ggare. Den handl\u00e4ggare som ansvarar f\u00f6r att vidta \u00e5tg\u00e4rder slutf\u00f6r operationen. Det h\u00e4r designm\u00f6nstret anv\u00e4nds ofta vid utformning av anv\u00e4ndargr\u00e4nssnitt, d\u00e4r flera lager av komponenter kan hantera en h\u00e4ndelse f\u00f6r anv\u00e4ndarinmatning. Det kan exempelvis handla om en ber\u00f6ring eller en svepning.<\/p>\n<p>Nedan s\u00e5 ser du ett exempel p\u00e5 en upptrappning av ett klagom\u00e5l med hj\u00e4lp av m\u00f6nstret Chain of Responsibility. Klagom\u00e5let hanteras av handl\u00e4ggarna p\u00e5 grundval av dess sv\u00e5righetsgrad:<\/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>Det uppenbara problemet med det h\u00e4r m\u00f6nstret \u00e4r att det \u00e4r linj\u00e4rt. Som ett resultat s\u00e5 kan det uppst\u00e5 en viss latenstid i hanteringen av en operation n\u00e4r ett stort antal handl\u00e4ggare \u00e4r kedjade till varandra.<\/p>\n<p>Att h\u00e5lla reda p\u00e5 alla handl\u00e4ggare kan vara en annan sv\u00e5righet, eftersom det kan bli ganska r\u00f6rigt efter ett visst antal handl\u00e4ggare. Fels\u00f6kning \u00e4r \u00e4nnu en mardr\u00f6m eftersom varje beg\u00e4ran kan hamna hos olika handl\u00e4ggare, vilket g\u00f6r det sv\u00e5rt f\u00f6r dig att standardisera <a href=\"https:\/\/kinqsta.com\/blog\/node-debug\/\">loggnings- och fels\u00f6kningsprocessen<\/a>.<\/p>\n<h4>14. Iterator<\/h4>\n<p>Iterator-m\u00f6nstret \u00e4r ganska enkelt och anv\u00e4nds mycket ofta i n\u00e4stan alla moderna objektorienterade spr\u00e5k. Du kanske st\u00e5r inf\u00f6r uppgiften att g\u00e5 igenom en lista med objekt som inte alla \u00e4r av samma typ. D\u00e5 kan normala iterations-metoder, som exempelvis for-slingor, bli ganska r\u00f6riga &#8211; s\u00e4rskilt om du \u00e4ven skriver aff\u00e4rslogik inuti dem.<\/p>\n<p>Iterator-m\u00f6nstret kan hj\u00e4lpa dig att isolera iterations- och bearbetningslogiken f\u00f6r dina listor fr\u00e5n den huvudsakliga aff\u00e4rslogiken.<\/p>\n<p>H\u00e4r ser du hur du kan anv\u00e4nda det p\u00e5 en ganska enkel lista med flera typer av element:<\/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>Det h\u00e4r m\u00f6nstret kan vara on\u00f6digt komplicerat f\u00f6r listor utan flera typer av element. Om det dessutom finns f\u00f6r m\u00e5nga typer av element i en lista s\u00e5 kan det \u00e4ven bli sv\u00e5rt att hantera.<\/p>\n<p>Nyckeln \u00e4r att identifiera om du verkligen beh\u00f6ver en iterator utifr\u00e5n din lista och dess framtida \u00e4ndringsm\u00f6jligheter. Dessutom s\u00e5 \u00e4r Iterator-m\u00f6nstret endast anv\u00e4ndbart i listor. Dessa kan ibland begr\u00e4nsa dig till deras linj\u00e4ra \u00e5tkomsts\u00e4tt. Andra datastrukturer kan ibland ge dig st\u00f6rre prestanda-f\u00f6rdelar.<\/p>\n<h4>15. Mediator<\/h4>\n<p>Din applikations-design kan ibland kr\u00e4va att du leker med ett stort antal olika objekt som rymmer olika typer av aff\u00e4rslogik och som ofta \u00e4r beroende av varandra. Hanteringen av beroendena kan ibland bli knepig eftersom du m\u00e5ste h\u00e5lla reda p\u00e5 hur dessa objekt utbyter data och kontrollen mellan dem.<\/p>\n<p>Designm\u00f6nstret Mediator syftar till att hj\u00e4lpa dig att l\u00f6sa detta problem genom att isolera interaktions-logiken f\u00f6r dessa objekt i ett separat objekt i sig sj\u00e4lvt.<\/p>\n<p>Detta separata objekt kallas mediator och ansvarar f\u00f6r att f\u00e5 arbetet utf\u00f6rt av dina klasser p\u00e5 l\u00e4gre niv\u00e5. Din klient eller den anropande milj\u00f6n kommer \u00e4ven att interagera med mediator i st\u00e4llet f\u00f6r med de l\u00e4gre klasserna.<\/p>\n<p>H\u00e4r \u00e4r ett exempel p\u00e5 hur designm\u00f6nstret mediator fungerar:<\/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>Mediator ger visserligen din appdesign frikoppling och stor flexibilitet. I slut\u00e4ndan s\u00e5 \u00e4r det dock ytterligare en klass som du m\u00e5ste underh\u00e5lla. Du m\u00e5ste bed\u00f6ma om din design verkligen kan dra nytta av en mediator innan du skriver en s\u00e5dan s\u00e5 att du inte till slut l\u00e4gger till en on\u00f6dig komplexitet i din kodbas.<\/p>\n<p>Det \u00e4r \u00e4ven viktigt att komma ih\u00e5g att \u00e4ven om mediator-klassen inte inneh\u00e5ller n\u00e5gon direkt aff\u00e4rslogik s\u00e5 inneh\u00e5ller den fortfarande en hel del kod. Den \u00e4r avg\u00f6rande f\u00f6r att din app ska fungera och kan d\u00e4rf\u00f6r snabbt bli ganska komplex.<\/p>\n<h4>16. Memento<\/h4>\n<p>Versionerings-objekt \u00e4r ett annat vanligt problem som du m\u00f6ter n\u00e4r du utvecklar appar. Det finns m\u00e5nga anv\u00e4ndningsomr\u00e5den d\u00e4r du beh\u00f6ver uppr\u00e4tth\u00e5lla ett objekts historik, st\u00f6dja enkla rollbacks och ibland \u00e4ven st\u00f6dja \u00e5terst\u00e4llning av dessa rollbacks. Att skriva logiken f\u00f6r s\u00e5dana appar kan vara sv\u00e5rt.<\/p>\n<p>Designm\u00f6nstret Memento \u00e4r t\u00e4nkt att l\u00f6sa detta problem p\u00e5 ett enkelt s\u00e4tt.<\/p>\n<p>En memento anses vara en \u00f6gonblicksbild av ett objekt vid en viss tidpunkt. Designm\u00f6nstret Memento anv\u00e4nder sig av dessa minnesbilder f\u00f6r att bevara \u00f6gonblicksbilder av objektet n\u00e4r det \u00e4ndras \u00f6ver tiden. N\u00e4r du beh\u00f6ver \u00e5terg\u00e5 till en gammal version s\u00e5 kan du helt enkelt h\u00e4mta upp minnet f\u00f6r den.<\/p>\n<p>S\u00e5 h\u00e4r kan du implementera detta i en textbehandlingsapp:<\/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>Memento-designm\u00f6nstret \u00e4r en utm\u00e4rkt l\u00f6sning f\u00f6r att hantera ett objekts historik, men det kan bli mycket resurskr\u00e4vande. Varje Memento \u00e4r n\u00e4stan en kopia av objektet. Som ett resultat s\u00e5 kan det snabbt sv\u00e4lla upp appens minne om det inte anv\u00e4nds med m\u00e5tta.<\/p>\n<p>Med ett stort antal objekt s\u00e5 kan hanteringen av deras livscykel \u00e4ven bli en ganska tr\u00e5kig uppgift. Ut\u00f6ver allt detta s\u00e5 \u00e4r klasserna <code>Originator<\/code> och <code>Caretaker<\/code> vanligtvis mycket t\u00e4tt kopplade, vilket \u00f6kar komplexiteten i din kodbas.<\/p>\n<h4>17. Observer<\/h4>\n<p>Observer-m\u00f6nstret erbjuder en alternativ l\u00f6sning p\u00e5 problemet med interaktion mellan flera objekt (som tidigare har setts i Mediator-m\u00f6nstret).<\/p>\n<p>Ist\u00e4llet f\u00f6r att l\u00e5ta varje objekt kommunicera med varandra genom en utsedd mediator s\u00e5 g\u00f6r m\u00f6nstret Observer att de kan observera varandra. Objekten \u00e4r utformade f\u00f6r att s\u00e4nda ut h\u00e4ndelser n\u00e4r de f\u00f6rs\u00f6ker s\u00e4nda data eller kontroll, och andra objekt som &#8221;lyssnar&#8221; p\u00e5 dessa h\u00e4ndelser kan sedan ta emot dem och interagera utifr\u00e5n deras inneh\u00e5ll.<\/p>\n<p>H\u00e4r \u00e4r en enkel demonstration av att skicka ut nyhetsbrev till flera personer med hj\u00e4lp av Observer-m\u00f6nstret:<\/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>Observer-m\u00f6nstret \u00e4r visserligen ett smidigt s\u00e4tt att skicka vidare kontroll och data. Det \u00e4r dock b\u00e4ttre l\u00e4mpat f\u00f6r situationer d\u00e4r det finns ett stort antal avs\u00e4ndare och mottagare som interagerar med varandra via ett begr\u00e4nsat antal anslutningar. Om objekten skulle ha en-till-en-anslutningar s\u00e5 skulle du f\u00f6rlora den f\u00f6rdel som du f\u00e5r genom att publicera och prenumerera p\u00e5 h\u00e4ndelser. Det kommer n\u00e4mligen alltid bara att finnas en prenumerant f\u00f6r varje publicerare (n\u00e4r det hade varit b\u00e4ttre om det hade hanterats med en direkt kommunikationslinje mellan dem).<\/p>\n<p>Dessutom s\u00e5 kan designm\u00f6nstret Observer leda till prestandaproblem om prenumerations-h\u00e4ndelserna inte hanteras korrekt. Om ett objekt forts\u00e4tter att prenumerera p\u00e5 ett annat objekt \u00e4ven n\u00e4r det inte beh\u00f6ver det, s\u00e5 kommer det\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Lapsed_listener_problem\">inte att vara ber\u00e4ttigat till garbage collection<\/a> och kommer att \u00f6ka minnesf\u00f6rbrukningen i appen.<\/p>\n<h4>18. Tillst\u00e5nd<\/h4>\n<p>Designm\u00f6nstret State \u00e4r ett av de mest anv\u00e4nda designm\u00f6nstren inom mjukvaruutvecklings-industrin. Popul\u00e4ra <a href=\"https:\/\/kinqsta.com\/se\/blog\/javascript-biblioteken\/\">JavaScript-ramverk<\/a> som <a href=\"https:\/\/reactjs.org\/docs\/state-and-lifecycle.html\">React<\/a> och <a href=\"https:\/\/medium.com\/olricdigital\/introduction-to-state-management-in-angular-v2-ef6f5144bade\">Angular<\/a> f\u00f6rlitar sig i h\u00f6g grad p\u00e5 State-m\u00f6nstret f\u00f6r att hantera data och app-beteende som \u00e4r baserat p\u00e5 dessa data.<\/p>\n<p>Enkelt uttryckt s\u00e5 \u00e4r State-designm\u00f6nstret anv\u00e4ndbart i situationer d\u00e4r du kan definiera definitiva tillst\u00e5nd f\u00f6r en enhet (som kan vara en komponent, en sida, en app eller en maskin), och enheten har en f\u00f6rdefinierad reaktion p\u00e5 tillst\u00e5nds-f\u00f6r\u00e4ndringen.<\/p>\n<p>L\u00e5t oss s\u00e4ga att du f\u00f6rs\u00f6ker bygga en l\u00e5neans\u00f6kans-process. Varje steg i ans\u00f6kningsprocessen kan definieras som ett tillst\u00e5nd.<\/p>\n<p>Medan kunden vanligtvis ser en liten lista med f\u00f6renklade tillst\u00e5nd f\u00f6r sin ans\u00f6kan (v\u00e4ntande, under granskning, accepterad och avslagen) s\u00e5 kan det finnas andra steg som \u00e4r inblandade internt. I varje steg s\u00e5 tilldelas ans\u00f6kan en s\u00e4rskild person och kan ha unika krav.<\/p>\n<p>Systemet \u00e4r utformat p\u00e5 ett s\u00e5dant s\u00e4tt att n\u00e4r behandlingen av en ans\u00f6kan \u00e4r avslutad i ett tillst\u00e5nd s\u00e5 uppdateras det till n\u00e4sta tillst\u00e5nd och n\u00e4sta relevanta steg p\u00e5b\u00f6rjas.<\/p>\n<p>S\u00e5 h\u00e4r kan du bygga ett system f\u00f6r uppgiftshantering med hj\u00e4lp av designm\u00f6nstret 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>State-m\u00f6nstret g\u00f6r visserligen ett bra jobb n\u00e4r det g\u00e4ller att separera steg i en process. Det kan dock bli extremt sv\u00e5rt att underh\u00e5lla i stora applikationer som har flera tillst\u00e5nd.<\/p>\n<p>Din process-design till\u00e5ter kanske dessutom mer \u00e4n bara linj\u00e4r r\u00f6relse genom alla tillst\u00e5nd. Som ett resultat s\u00e5 f\u00e5r du skriva och underh\u00e5lla mer kod, eftersom varje \u00f6verg\u00e5ng till ett tillst\u00e5nd m\u00e5ste hanteras separat.<\/p>\n<h4>19. Strategi<\/h4>\n<p>Strategy-m\u00f6nstret, \u00e4ven k\u00e4nt som Policy-m\u00f6nstret, syftar till att hj\u00e4lpa dig att kapsla in och fritt utbyta klasser med hj\u00e4lp av ett gemensamt gr\u00e4nssnitt. Detta bidrar till att uppr\u00e4tth\u00e5lla en l\u00f6s koppling mellan klienten och klasserna och g\u00f6r att du kan l\u00e4gga till s\u00e5 m\u00e5nga implementeringar som du vill.<\/p>\n<p>Strategy-m\u00f6nstret \u00e4r k\u00e4nt f\u00f6r att vara till stor hj\u00e4lp i situationer d\u00e4r samma operation beh\u00f6vs med hj\u00e4lp av olika metoder\/algoritmer, eller d\u00e4r massiva switchblock m\u00e5ste ers\u00e4ttas med mer m\u00e4nniskov\u00e4nlig kod.<\/p>\n<p>H\u00e4r \u00e4r ett exempel p\u00e5 Strategy-m\u00f6nstret:<\/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>Strategy-m\u00f6nstret \u00e4r utm\u00e4rkt n\u00e4r det g\u00e4ller att inf\u00f6ra nya varianter av en enhet utan att \u00e4ndra klienterna s\u00e4rskilt mycket. Det kan dock verka \u00f6verdrivet om du bara har en handfull variationer att implementera.<\/p>\n<p>Dessutom s\u00e5 tar kapslingen bort finare detaljer om varje variants interna logik. Som ett resultat s\u00e5 \u00e4r din klient omedveten om hur en variant kommer att bete sig.<\/p>\n<h4>20. Visitor<\/h4>\n<p>Visitor-m\u00f6nstret syftar till att hj\u00e4lpa dig att g\u00f6ra din kod utbyggbar.<\/p>\n<p>Tanken \u00e4r att tillhandah\u00e5lla en metod i klassen som g\u00f6r det m\u00f6jligt f\u00f6r objekt fr\u00e5n andra klasser att enkelt g\u00f6ra \u00e4ndringar i objekt fr\u00e5n den aktuella klassen. De andra objekten <em>bes\u00f6ker<\/em> det aktuella objektet (\u00e4ven kallat plats-objektet). Det kan \u00e4ven h\u00e4nda att den aktuella klassen <em>accepterar <\/em>bes\u00f6karobjekten och plats-objektet hanterar bes\u00f6ket av varje externt objekt p\u00e5 l\u00e4mpligt s\u00e4tt.<\/p>\n<p>S\u00e5 h\u00e4r kan du anv\u00e4nda detta:<\/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>Den enda bristen i den h\u00e4r konstruktionen \u00e4r att varje bes\u00f6karklass m\u00e5ste uppdateras n\u00e4r en ny plats l\u00e4ggs till eller \u00e4ndras. I fall d\u00e4r flera bes\u00f6kare och platsobjekt finns tillsammans s\u00e5 kan detta vara sv\u00e5rt att underh\u00e5lla.<\/p>\n<p>I \u00f6vrigt s\u00e5 fungerar metoden utm\u00e4rkt f\u00f6r att f\u00f6rb\u00e4ttra funktionaliteten hos klasser dynamiskt.<\/p>\n<h2>B\u00e4sta praxis f\u00f6r att genomf\u00f6ra designm\u00f6nster<\/h2>\n<p>Nu n\u00e4r du har sett de vanligaste designm\u00f6nstren i JavaScript s\u00e5 kommer h\u00e4r n\u00e5gra tips som du b\u00f6r t\u00e4nka p\u00e5 n\u00e4r du implementerar dem.<\/p>\n<h3>Var s\u00e4rskilt noga med att f\u00f6rst\u00e5 om ett m\u00f6nster passar f\u00f6r l\u00f6sningen<\/h3>\n<p>Det h\u00e4r tipset ska till\u00e4mpas innan du implementerar ett designm\u00f6nster i din k\u00e4llkod. Det kan visserligen se ut som att ett designm\u00f6nster \u00e4r slutet p\u00e5 alla dina bekymmer. F\u00f6rs\u00f6k dock att analysera kritiskt om detta \u00e4r sant.<\/p>\n<p>Det finns m\u00e5nga m\u00f6nster som l\u00f6ser samma problem, men som har olika tillv\u00e4gag\u00e5ngss\u00e4tt och olika konsekvenser. Dina kriterier f\u00f6r att v\u00e4lja ett designm\u00f6nster b\u00f6r med andra ord inte bara vara om det l\u00f6ser ditt problem eller inte. De b\u00f6r \u00e4ven ta h\u00e4nsyn till hur bra det l\u00f6ser ditt problem och om det finns n\u00e5got annat m\u00f6nster som kan presentera en mer effektiv l\u00f6sning.<\/p>\n<h3>F\u00f6rst\u00e5 kostnaderna f\u00f6r att implementera ett m\u00f6nster innan du b\u00f6rjar<\/h3>\n<p>\u00c4ven om designm\u00f6nster verkar vara den b\u00e4sta l\u00f6sningen p\u00e5 alla <a href=\"https:\/\/kinqsta.com\/blog\/errors-in-javascript\/\">tekniska problem<\/a> s\u00e5 b\u00f6r du inte hoppa in i implementeringen av dem i din k\u00e4llkod direkt.<\/p>\n<p>N\u00e4r du bed\u00f6mer konsekvenserna av att implementera en l\u00f6sning s\u00e5 m\u00e5ste du \u00e4ven ta h\u00e4nsyn till din egen situation. Har du ett stort team av mjukvaruutvecklare som \u00e4r skickliga p\u00e5 att f\u00f6rst\u00e5 och underh\u00e5lla designm\u00f6nster? Eller \u00e4r du en grundare i ett tidigt skede med ett minimalt utvecklingsteam som vill sl\u00e4ppa en snabb MVP av din produkt? Om du svarar ja p\u00e5 den sista fr\u00e5gan s\u00e5 \u00e4r designm\u00f6nster kanske inte det mest optimala utvecklingss\u00e4ttet f\u00f6r dig.<\/p>\n<p>Designm\u00f6nster leder inte till en stor \u00e5teranv\u00e4ndning av kod om de inte planeras i ett mycket tidigt skede av app-designen. Att slumpm\u00e4ssigt anv\u00e4nda designm\u00f6nster i olika skeden kan leda till en on\u00f6digt komplex app-arkitektur som du m\u00e5ste \u00e4gna veckor \u00e5t att f\u00f6renkla.<\/p>\n<p>Effektiviteten hos ett designm\u00f6nster kan inte bed\u00f6mas genom n\u00e5gon form av testning. Det \u00e4r ditt <a href=\"https:\/\/kinqsta.com\/se\/blog\/kodgranskningsverktygen\/\">teams erfarenhet och introspektion<\/a> som g\u00f6r att du vet om de fungerar. Om du d\u00e4remot har tid och resurser att avs\u00e4tta f\u00f6r dessa aspekter s\u00e5 kan designm\u00f6nster verkligen l\u00f6sa dina problem.<\/p>\n<h3>G\u00f6r inte varje l\u00f6sning till ett m\u00f6nster<\/h3>\n<p>En annan tumregel att h\u00e5lla i minnet \u00e4r att avst\u00e5 fr\u00e5n att f\u00f6rs\u00f6ka g\u00f6ra varje litet problem-l\u00f6sningspar till ett designm\u00f6nster. D\u00e5 kanske du b\u00f6rjar att anv\u00e4nda detta \u00f6verallt.<\/p>\n<p>Det \u00e4r visserligen bra att identifiera standardl\u00f6sningar och ha dem i \u00e5tanke n\u00e4r du st\u00f6ter p\u00e5 liknande problem. Men det kan \u00e4ven h\u00e4nda att det nya problemet som du har st\u00f6tt p\u00e5 inte passar in p\u00e5 exakt samma beskrivning som ett \u00e4ldre problem. I ett s\u00e5dant fall s\u00e5 kan det sluta med att du implementerar en suboptimal l\u00f6sning och sl\u00f6sar bort resurser.<\/p>\n<p>Designm\u00f6nster \u00e4r idag etablerade som ledande exempel p\u00e5 problem-l\u00f6sningspar eftersom de har testats av hundratals och tusentals programmerare \u00f6ver tid. Som ett resultat s\u00e5 har de generaliserats s\u00e5 mycket som m\u00f6jligt. Om du f\u00f6rs\u00f6ker att replikera den anstr\u00e4ngningen genom att bara titta p\u00e5 en massa problem och l\u00f6sningar och kalla dem likartade s\u00e5 kan det sluta med att du g\u00f6r mycket mer skada p\u00e5 din kod \u00e4n vad du n\u00e5gonsin hade f\u00f6rv\u00e4ntat dig.<\/p>\n<h2>N\u00e4r b\u00f6r du anv\u00e4nda designm\u00f6nster?<\/h2>\n<p>F\u00f6r att sammanfatta det hela s\u00e5 kommer h\u00e4r n\u00e5gra ledtr\u00e5dar som du b\u00f6r h\u00e5lla utkik efter n\u00e4r det g\u00e4ller designm\u00f6nster. Alla g\u00e4ller inte f\u00f6r varje app-utveckling, men de b\u00f6r ge dig en bra uppfattning om vad du ska titta efter n\u00e4r du funderar p\u00e5 att anv\u00e4nda designm\u00f6nster:<\/p>\n<ul>\n<li>Du har ett starkt internt team av utvecklare som f\u00f6rst\u00e5r designm\u00f6nster v\u00e4l.<\/li>\n<li>Du f\u00f6ljer en SDLC-modell som ger utrymme f\u00f6r djupg\u00e5ende diskussioner om appens arkitektur, och designm\u00f6nster har tagits upp i dessa diskussioner.<\/li>\n<li>Samma upps\u00e4ttning problem har dykt upp flera g\u00e5nger i dina diskussioner om design och du vet vilket designm\u00f6nster som passar f\u00f6r detta.<\/li>\n<li>Du har f\u00f6rs\u00f6kt att l\u00f6sa en mindre variant av ditt problem sj\u00e4lvst\u00e4ndigt med designm\u00f6nstret.<\/li>\n<li>Med designm\u00f6nstret p\u00e5 plats s\u00e5 ser din kod inte \u00f6verdrivet komplex ut.<\/li>\n<\/ul>\n<p>Om ett designm\u00f6nster l\u00f6ser ditt problem <em>och<\/em> hj\u00e4lper dig att skriva en kod som \u00e4r enkel, \u00e5teranv\u00e4ndbar, modul\u00e4r, l\u00f6st kopplad och tydlig s\u00e5 kan detta vara r\u00e4tt v\u00e4g att g\u00e5.<\/p>\n<p>Ett annat bra tips att t\u00e4nka p\u00e5 \u00e4r att allt inte handlar om designm\u00f6nster. Designm\u00f6nster \u00e4r avsedda att hj\u00e4lpa dig att l\u00f6sa problem. De \u00e4r inte lagar och regler som man m\u00e5ste f\u00f6lja. Faktum \u00e4r att de ultimata reglerna och lagarna fortfarande \u00e4r desamma: H\u00e5ll din kod ren, enkel, l\u00e4sbar och skalbar. Om ett designm\u00f6nster hj\u00e4lper dig att g\u00f6ra detta samtidigt som det l\u00f6ser ditt problem, b\u00f6r du kunna anv\u00e4nda det.<\/p>\n<h2>Sammanfattning<\/h2>\n<p>JavaScript-designm\u00f6nster \u00e4r ett underbart s\u00e4tt att n\u00e4rma sig problem som flera programmerare har st\u00e4llts inf\u00f6r under tidens g\u00e5ng. De presenterar bepr\u00f6vade l\u00f6sningar som str\u00e4var efter att h\u00e5lla din kodbas ren och l\u00f6st kopplad.<\/p>\n<p>Idag s\u00e5 finns det <a href=\"https:\/\/sourcemaking.com\/design-patterns-and-tips\">hundratals tillg\u00e4ngliga designm\u00f6nster<\/a> som n\u00e4stan l\u00f6ser alla problem som du st\u00f6ter p\u00e5 n\u00e4r du bygger appar. Alla designm\u00f6nster l\u00f6ser dock inte dina problem varje g\u00e5ng.<\/p>\n<p>Precis som alla <a href=\"https:\/\/kinqsta.com\/se\/blog\/react-basta-praxis\/\">andra programmeringskonventioner<\/a> s\u00e5 \u00e4r designm\u00f6nster avsedda att tas som f\u00f6rslag f\u00f6r att l\u00f6sa problem. De \u00e4r inte lagar som ska f\u00f6ljas hela tiden, och om du behandlar dem som lagar kan det sluta med att du g\u00f6r stor skada p\u00e5 dina appar.<\/p>\n<p>N\u00e4r din app \u00e4r klar s\u00e5 beh\u00f6ver du en plats att hysa den p\u00e5 &#8211; och <a href=\"https:\/\/sevalla.com\/application-hosting\/\">Kinsta&#8217;s l\u00f6sningar f\u00f6r applikationshosting<\/a> \u00e4r bland de snabbaste och mest tillf\u00f6rlitliga. Du beh\u00f6ver bara logga in p\u00e5 ditt <a href=\"https:\/\/kinqsta.com\/se\/mykinsta\/\">MyKinsta-konto<\/a> (Kinsta&#8217;s anpassade administrativa instrumentpanel), ansluta till ditt <a href=\"https:\/\/kinqsta.com\/blog\/what-is-github\/\">GitHub-arkiv<\/a> och starta! Dessutom s\u00e5 debiteras du endast f\u00f6r de resurser som din app anv\u00e4nder.<\/p>\n<p>Vilka designm\u00f6nster anv\u00e4nder du regelbundet i ditt arbete med programvaru-programmering? Finns det ett m\u00f6nster som vi missade i listan? L\u00e5t oss veta detta i kommentarerna nedan!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>N\u00e4r du bygger JavaScript-applikationer s\u00e5 kan du st\u00f6ta p\u00e5 scenarier d\u00e4r du m\u00e5ste bygga objekt p\u00e5 ett visst, f\u00f6rdefinierat s\u00e4tt. Det kan \u00e4ven h\u00e4nda att du &#8230;<\/p>\n","protected":false},"author":238,"featured_media":50034,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kinsta_gated_content":false,"_kinsta_gated_content_redirect":"","footnotes":""},"tags":[],"topic":[784],"class_list":["post-50033","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","topic-javascript-sjalvstudier"],"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>En omfattande guide om JavaScript-designm\u00f6nster<\/title>\n<meta name=\"description\" content=\"Det finns m\u00e4ngder av JavaScript-designm\u00f6nster som kan spara tid och anstr\u00e4ngning. L\u00e4s om dessa \u00e5teranv\u00e4ndbara l\u00f6sningar i detta inl\u00e4gg.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/\" \/>\n<meta property=\"og:locale\" content=\"sv_SE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"En omfattande guide om JavaScript-designm\u00f6nster\" \/>\n<meta property=\"og:description\" content=\"Det finns m\u00e4ngder av JavaScript-designm\u00f6nster som kan spara tid och anstr\u00e4ngning. L\u00e4s om dessa \u00e5teranv\u00e4ndbara l\u00f6sningar i detta inl\u00e4gg.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/\" \/>\n<meta property=\"og:site_name\" content=\"Kinsta\u00ae\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/kinstasweden\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-02-14T08:33:39+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-09-18T10:21:25+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/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=\"Det finns m\u00e4ngder av JavaScript-designm\u00f6nster som kan spara tid och anstr\u00e4ngning. L\u00e4s om dessa \u00e5teranv\u00e4ndbara l\u00f6sningar i detta inl\u00e4gg.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/02\/javascript-design-patterns.png\" \/>\n<meta name=\"twitter:creator\" content=\"@kinsta_se\" \/>\n<meta name=\"twitter:site\" content=\"@kinsta_se\" \/>\n<meta name=\"twitter:label1\" content=\"Skriven av\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kumar Harsh\" \/>\n\t<meta name=\"twitter:label2\" content=\"Ber\u00e4knad l\u00e4stid\" \/>\n\t<meta name=\"twitter:data2\" content=\"51 minuter\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/\"},\"author\":{\"name\":\"Kumar Harsh\",\"@id\":\"https:\/\/kinqsta.com\/se\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9\"},\"headline\":\"En omfattande guide om JavaScript-designm\u00f6nster\",\"datePublished\":\"2023-02-14T08:33:39+00:00\",\"dateModified\":\"2023-09-18T10:21:25+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/\"},\"wordCount\":6834,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/kinqsta.com\/se\/#organization\"},\"image\":{\"@id\":\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/02\/javascript-design-patterns.png\",\"inLanguage\":\"sv-SE\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/\",\"url\":\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/\",\"name\":\"En omfattande guide om JavaScript-designm\u00f6nster\",\"isPartOf\":{\"@id\":\"https:\/\/kinqsta.com\/se\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/02\/javascript-design-patterns.png\",\"datePublished\":\"2023-02-14T08:33:39+00:00\",\"dateModified\":\"2023-09-18T10:21:25+00:00\",\"description\":\"Det finns m\u00e4ngder av JavaScript-designm\u00f6nster som kan spara tid och anstr\u00e4ngning. L\u00e4s om dessa \u00e5teranv\u00e4ndbara l\u00f6sningar i detta inl\u00e4gg.\",\"breadcrumb\":{\"@id\":\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#breadcrumb\"},\"inLanguage\":\"sv-SE\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"sv-SE\",\"@id\":\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#primaryimage\",\"url\":\"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/02\/javascript-design-patterns.png\",\"contentUrl\":\"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/02\/javascript-design-patterns.png\",\"width\":1460,\"height\":730},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/kinqsta.com\/se\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"JavaScript-sj\u00e4lvstudier\",\"item\":\"https:\/\/kinqsta.com\/se\/topics\/javascript-sjalvstudier\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"En omfattande guide om JavaScript-designm\u00f6nster\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/kinqsta.com\/se\/#website\",\"url\":\"https:\/\/kinqsta.com\/se\/\",\"name\":\"Kinsta\u00ae\",\"description\":\"Snabba, s\u00e4kra, premium hosting-l\u00f6sningar\",\"publisher\":{\"@id\":\"https:\/\/kinqsta.com\/se\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/kinqsta.com\/se\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"sv-SE\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/kinqsta.com\/se\/#organization\",\"name\":\"Kinsta\",\"url\":\"https:\/\/kinqsta.com\/se\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"sv-SE\",\"@id\":\"https:\/\/kinqsta.com\/se\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/12\/kinsta-logo.jpeg\",\"contentUrl\":\"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/12\/kinsta-logo.jpeg\",\"width\":500,\"height\":500,\"caption\":\"Kinsta\"},\"image\":{\"@id\":\"https:\/\/kinqsta.com\/se\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/kinstasweden\/\",\"https:\/\/x.com\/kinsta_se\",\"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:\/\/kinqsta.com\/se\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9\",\"name\":\"Kumar Harsh\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"sv-SE\",\"@id\":\"https:\/\/kinqsta.com\/se\/#\/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:\/\/kinqsta.com\/se\/blog\/author\/kumarharsh\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"En omfattande guide om JavaScript-designm\u00f6nster","description":"Det finns m\u00e4ngder av JavaScript-designm\u00f6nster som kan spara tid och anstr\u00e4ngning. L\u00e4s om dessa \u00e5teranv\u00e4ndbara l\u00f6sningar i detta inl\u00e4gg.","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:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/","og_locale":"sv_SE","og_type":"article","og_title":"En omfattande guide om JavaScript-designm\u00f6nster","og_description":"Det finns m\u00e4ngder av JavaScript-designm\u00f6nster som kan spara tid och anstr\u00e4ngning. L\u00e4s om dessa \u00e5teranv\u00e4ndbara l\u00f6sningar i detta inl\u00e4gg.","og_url":"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/","og_site_name":"Kinsta\u00ae","article_publisher":"https:\/\/www.facebook.com\/kinstasweden\/","article_published_time":"2023-02-14T08:33:39+00:00","article_modified_time":"2023-09-18T10:21:25+00:00","og_image":[{"width":1460,"height":730,"url":"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/02\/javascript-design-patterns.png","type":"image\/png"}],"author":"Kumar Harsh","twitter_card":"summary_large_image","twitter_description":"Det finns m\u00e4ngder av JavaScript-designm\u00f6nster som kan spara tid och anstr\u00e4ngning. L\u00e4s om dessa \u00e5teranv\u00e4ndbara l\u00f6sningar i detta inl\u00e4gg.","twitter_image":"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/02\/javascript-design-patterns.png","twitter_creator":"@kinsta_se","twitter_site":"@kinsta_se","twitter_misc":{"Skriven av":"Kumar Harsh","Ber\u00e4knad l\u00e4stid":"51 minuter"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#article","isPartOf":{"@id":"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/"},"author":{"name":"Kumar Harsh","@id":"https:\/\/kinqsta.com\/se\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9"},"headline":"En omfattande guide om JavaScript-designm\u00f6nster","datePublished":"2023-02-14T08:33:39+00:00","dateModified":"2023-09-18T10:21:25+00:00","mainEntityOfPage":{"@id":"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/"},"wordCount":6834,"commentCount":0,"publisher":{"@id":"https:\/\/kinqsta.com\/se\/#organization"},"image":{"@id":"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#primaryimage"},"thumbnailUrl":"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/02\/javascript-design-patterns.png","inLanguage":"sv-SE","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/","url":"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/","name":"En omfattande guide om JavaScript-designm\u00f6nster","isPartOf":{"@id":"https:\/\/kinqsta.com\/se\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#primaryimage"},"image":{"@id":"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#primaryimage"},"thumbnailUrl":"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/02\/javascript-design-patterns.png","datePublished":"2023-02-14T08:33:39+00:00","dateModified":"2023-09-18T10:21:25+00:00","description":"Det finns m\u00e4ngder av JavaScript-designm\u00f6nster som kan spara tid och anstr\u00e4ngning. L\u00e4s om dessa \u00e5teranv\u00e4ndbara l\u00f6sningar i detta inl\u00e4gg.","breadcrumb":{"@id":"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#breadcrumb"},"inLanguage":"sv-SE","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/"]}]},{"@type":"ImageObject","inLanguage":"sv-SE","@id":"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#primaryimage","url":"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/02\/javascript-design-patterns.png","contentUrl":"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/02\/javascript-design-patterns.png","width":1460,"height":730},{"@type":"BreadcrumbList","@id":"https:\/\/kinqsta.com\/se\/blog\/javascript-design-monster\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/kinqsta.com\/se\/"},{"@type":"ListItem","position":2,"name":"JavaScript-sj\u00e4lvstudier","item":"https:\/\/kinqsta.com\/se\/topics\/javascript-sjalvstudier\/"},{"@type":"ListItem","position":3,"name":"En omfattande guide om JavaScript-designm\u00f6nster"}]},{"@type":"WebSite","@id":"https:\/\/kinqsta.com\/se\/#website","url":"https:\/\/kinqsta.com\/se\/","name":"Kinsta\u00ae","description":"Snabba, s\u00e4kra, premium hosting-l\u00f6sningar","publisher":{"@id":"https:\/\/kinqsta.com\/se\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kinqsta.com\/se\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"sv-SE"},{"@type":"Organization","@id":"https:\/\/kinqsta.com\/se\/#organization","name":"Kinsta","url":"https:\/\/kinqsta.com\/se\/","logo":{"@type":"ImageObject","inLanguage":"sv-SE","@id":"https:\/\/kinqsta.com\/se\/#\/schema\/logo\/image\/","url":"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/12\/kinsta-logo.jpeg","contentUrl":"https:\/\/kinqsta.com\/se\/wp-content\/uploads\/sites\/9\/2023\/12\/kinsta-logo.jpeg","width":500,"height":500,"caption":"Kinsta"},"image":{"@id":"https:\/\/kinqsta.com\/se\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/kinstasweden\/","https:\/\/x.com\/kinsta_se","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:\/\/kinqsta.com\/se\/#\/schema\/person\/3a80efffa9cbb0333cc9c22b754415d9","name":"Kumar Harsh","image":{"@type":"ImageObject","inLanguage":"sv-SE","@id":"https:\/\/kinqsta.com\/se\/#\/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:\/\/kinqsta.com\/se\/blog\/author\/kumarharsh\/"}]}},"acf":[],"_links":{"self":[{"href":"https:\/\/kinqsta.com\/se\/wp-json\/wp\/v2\/posts\/50033","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kinqsta.com\/se\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kinqsta.com\/se\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kinqsta.com\/se\/wp-json\/wp\/v2\/users\/238"}],"replies":[{"embeddable":true,"href":"https:\/\/kinqsta.com\/se\/wp-json\/wp\/v2\/comments?post=50033"}],"version-history":[{"count":13,"href":"https:\/\/kinqsta.com\/se\/wp-json\/wp\/v2\/posts\/50033\/revisions"}],"predecessor-version":[{"id":51581,"href":"https:\/\/kinqsta.com\/se\/wp-json\/wp\/v2\/posts\/50033\/revisions\/51581"}],"alternate":[{"embeddable":true,"hreflang":"en","title":"English","href":"https:\/\/kinqsta.com\/se\/wp-json\/kinsta\/v1\/posts\/50033\/translations\/en"},{"embeddable":true,"hreflang":"it","title":"Italian","href":"https:\/\/kinqsta.com\/se\/wp-json\/kinsta\/v1\/posts\/50033\/translations\/it"},{"embeddable":true,"hreflang":"pt","title":"Portuguese","href":"https:\/\/kinqsta.com\/se\/wp-json\/kinsta\/v1\/posts\/50033\/translations\/pt"},{"embeddable":true,"hreflang":"fr","title":"French","href":"https:\/\/kinqsta.com\/se\/wp-json\/kinsta\/v1\/posts\/50033\/translations\/fr"},{"embeddable":true,"hreflang":"de","title":"German","href":"https:\/\/kinqsta.com\/se\/wp-json\/kinsta\/v1\/posts\/50033\/translations\/de"},{"embeddable":true,"hreflang":"ja","title":"Japanese","href":"https:\/\/kinqsta.com\/se\/wp-json\/kinsta\/v1\/posts\/50033\/translations\/jp"},{"embeddable":true,"hreflang":"nl","title":"Dutch","href":"https:\/\/kinqsta.com\/se\/wp-json\/kinsta\/v1\/posts\/50033\/translations\/nl"},{"embeddable":true,"hreflang":"es","title":"Spanish","href":"https:\/\/kinqsta.com\/se\/wp-json\/kinsta\/v1\/posts\/50033\/translations\/es"},{"embeddable":true,"hreflang":"sv","title":"Swedish","href":"https:\/\/kinqsta.com\/se\/wp-json\/kinsta\/v1\/posts\/50033\/translations\/se"},{"embeddable":true,"hreflang":"da","title":"Danish","href":"https:\/\/kinqsta.com\/se\/wp-json\/kinsta\/v1\/posts\/50033\/translations\/dk"},{"href":"https:\/\/kinqsta.com\/se\/wp-json\/kinsta\/v1\/posts\/50033\/tree"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kinqsta.com\/se\/wp-json\/wp\/v2\/media\/50034"}],"wp:attachment":[{"href":"https:\/\/kinqsta.com\/se\/wp-json\/wp\/v2\/media?parent=50033"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kinqsta.com\/se\/wp-json\/wp\/v2\/tags?post=50033"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/kinqsta.com\/se\/wp-json\/wp\/v2\/topic?post=50033"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}