Arv og utvide gjenstander med JavaScript

Hvis du er kjent med objektorientert programmering, er du mest sannsynlig kjent med subclassing og arv. Men arv har fått en dårlig rap. Jeg tror det er fordi noen utviklere ser det som en catch-all-løsning når du må endre et program. Problemet med dette er at klassehierarkier kan bli uhåndterlige. 

Det finnes andre designmønstre vi kan bruke til å gjøre appene våre lettere å forstå og klar for endring. Jeg vil vise deg eksempler på hvordan du kan bruke arv og dekoratør og sammensatt mønster for å forbedre programmets design.

Arv

Ideen bak arv er at ett objekt "er en" spesialisert versjon av et annet objekt. Det er en overordnet klasse (også kjent som en superklasse) som definerer basisegenskapene til objektet vårt. Og det er en barneklasse (underklasse) som arver eiendommens klasser. 

Et eksempel på arv er en hund og en puddel. Alle hundene har visse egenskaper som fire ben og evnen til å bjeffe. En puddel "er en" slags hund. En SUV er et kjøretøy. En sirkel er en form. Dette er hva vårt klasshierarki ville se ut om vi skulle designe et program for å lage former.

Fordelen med å ha en Shape-klasse er at vi kan gjenbruke egenskapene og metodene vi definerte i andre klasser. 

Legg merke til at getArea Metoden ble omdefinert i hver av våre underklasser. Vi trengte ikke å omdefinere denne metoden, men det gjorde vi for å erstatte foreldrenes implementering av metoden. Det er fordi hver form vil ha sin egen måte å beregne området på. 

Å overstyre en overordnet metode i en barneklasse er et eksempel på polymorfisme. Polymorfisme er evnen til objekter å ha flere former. Det tillater undergrupper å ha metoder med samme navn som deres superklasse, men med forskjellige implementeringer.  

Dette er et eksempel på hvordan vår kode vil se ut til å opprette en underklasse for Shape og Circle:

klasseform constructor (x, y) this.xPosition = x; this.yPosition = y;  getArea () ... klasse sirkel strekker seg form konstruktør (x, y, radius) super (x, y, radius); this.radius = radius getArea () ... la sirkel = ny sirkel (1,2,3);

En av ulempene ved dette designvalget er at hvis du bestemmer deg for foreldreklassen, må du endre seg, og det kan hende at underklassene må endres, sammen med alle de objektene vi opprettet. 

For eksempel, anta at vi senere bestemte oss for at det ville være bedre å erstatte x- og y-parametrene i Form-klassen med en gjenstand. Derfor vil vi måtte bytte konstruktøren for alle våre underklasser og argumentene for hvert objekt vi har opprettet.

Vi kan se hvordan dette lett kan bli problematisk. Vi måtte sørge for at vi fikk vår design rett første gang, slik at vi kunne unngå å gjøre endringer. Men det er ikke praktisk, og det er heller ikke det vi skal streve for. Et program er en stadig evolusjonerende enhet, og det er bedre for oss utviklere hvis vi har fleksibilitet til å gjøre endringer enkelt. I det minste bør vi ikke ha mer enn ett nivå av barneklasser.

Dekoratormønster

En dekoratør lar oss feste egenskapene til en gjenstand etter at de er opprettet. Dette betyr at vi kan legge til funksjonalitet uten underklasse eller være opptatt av implementeringen av objektet vårt. 

I stedet for å tenke er en sirkel en form, kan vi bruke Form-klassen til å lage sirkler og pakke den sammen med de ekstra egenskapene vi ønsker. Her er et alternativ til å lage sirkelobjekter ved hjelp av en dekoratør:

klasseform constructor (data) this.x = data.x; this.y = data.y;  getArea () ... funksjonen CircleDecorator (form) shape.radius = 3; shape.getArea = funksjon () ...; returnere form;  la form = ny form (x: 1, y: 2); la sirkel = ny CircleDecorator (form);

Vi kan legge til eller endre medlemmer av vår Form-klasse med en dekoratør i motsetning til å underklassere den. Med eksempeleksempelet kan du kanskje finne ut at du bare vil lage et sirkelobjekt som har alle egenskapene du trenger, og gjør det samme for andre former. Det er greit. Men en dekoratør gjør at vi kan bruke koden i vår Form-klasse og endre den med funksjonaliteten som avviker fra hver form. Som et resultat vil vi ha flere objekter, men flere objekter er enklere å administrere enn flere underklasser.

Dette mønsteret er ikke begrenset til å skape grafikk. Du kan bruke den i alle situasjoner der du vil legge til ansvar for et objekt. 

For eksempel kan vi ha en klasse som håndterer å registrere brukere på vår konto. Før vi lagrer informasjonen i databasen, vil det være lurt å kontrollere at inngangen er gyldig og ikke inneholder skadelige skript. Vi kunne dekorere klassen med en metode for å validere informasjonen først. Den samme dekoratøren kan gjenbrukes hvor som helst i vår søknad der vi aksepterer brukerinngang.

Sammensatt mønster

Objekter kan bestå av andre objekter. Visningen for en app kan betraktes som en komponent som består av andre visninger. Hvis vi skulle lage et spill, ville vår spillverden vise all vår grafikk vi opprettet som sirkler og firkanter. Hver gang vi oppdaterer vårt syn, må vi omdanne hvert element. Vi trenger en måte å administrere alle elementene som en gruppe på. 

Det er her komposittmønsteret kan hjelpe oss. Vi kan lage en klasse som er ansvarlig for alle elementene. Når vi vil omlegge elementene, kaller vi denne klassens tegnemetode, og det vil kalle tegnemetoden på hvert enkelt element.  

klasse Komponent konstruktør (navn) this.components = []; this.element = document.createElement (navn);  legg til (elem) this.components.push (elem);  tegne () for (const elem of this.components) elem.draw ();  klasse sirkel konstruktør (data) this.x = data.x; this.y = data.y; this.radius = data.radius;  getArea () ... draw () ... la verden = ny komponent ('div'); la sirkel = ny sirkel (x: 1, y: 1, radius: 2); la circle2 = ny sirkel (x: 10, y: 10, radius: 2); world.add (sirkel); world.add (CIRCLE2); world.draw ();

En nettside kan også betraktes som en komponent. Denne komponenten kan ha en meny, en sidebar og et blogginnlegg. Stillingen vil være en delkomponent som har et bilde, en tittel og en kropp. De tegne Metode for vår hovedapp komponent vil ringe tegne på menyen, sidebar og innlegg. Postkomponenten vil igjen ringe på postbildet, tittelen og kroppen. 

Her er en oversikt over hva en nettside vil dele opp i komponenter:

Dette mønsteret er ikke begrenset til å skape visninger. Hvis vi for eksempel laget et spill, kan vi ha en komponent til å administrere elementene på skjermen, en komponent for å administrere lyden og en komponent for å administrere spilltilstanden. 

Disse vil alle være inne i en komponent jeg kaller spillmotor. Spillmotoren ville ha en initialiseringsmetode som ville kalle initialiseringsmetoden på hver av dens underkomponenter. Det er kraften i å bruke komposittmønsteret. I stedet for å håndtere individuelle objekter kan vi behandle dem som ett objekt.  

Konklusjon

Arv gir oss mulighet til å gjenbruke koden ved å definere et objekt i form av en annen gjenstand. Dekoratormønsteret gir oss mulighet til å legge til ansvar på et objekt uten å endre den opprinnelige koden eller underklassen. Sammensatt mønster modellerer del-hele relasjoner. Disse mønstrene er ikke ment å brukes isolert. 

JavaScript har blitt språket for å jobbe på nettet. Det er ikke uten sine lærekurver, og det er nok av rammer og biblioteker for å holde deg opptatt også. Hvis du leter etter flere ressurser for å studere eller bruke i arbeidet ditt, sjekk ut hva vi har tilgjengelig på Envato Market.

De kan kombineres etter eget ønske. Eksemplene jeg oppgav, bør ikke tas som den eneste applikasjonen for bruk av mønstrene. De er bare en guide. Ta gjerne din kreativitet til å bruke dem. Det er ingen måte å implementere dem eller en brukstilfelle på.