Latviešu

Apgūstiet JavaScript dizaina rakstus, izmantojot mūsu pilnīgo ieviešanas rokasgrāmatu. Mācieties radīšanas, strukturālos un uzvedības rakstus ar praktiskiem koda piemēriem.

JavaScript Dizaina Raksti: Visaptveroša Ieviešanas Rokasgrāmata Mūsdienu Izstrādātājiem

Ievads: Stingra koda pamats

Dinamiskajā programmatūras izstrādes pasaulē uzrakstīt kodu, kas vienkārši strādā, ir tikai pirmais solis. Patiesais izaicinājums un profesionāla izstrādātāja pazīme ir radīt kodu, kas ir mērogojams, uzturams un viegli saprotams citiem, lai sadarbotos. Tieši šeit spēlē nāk dizaina raksti. Tie nav konkrēti algoritmi vai bibliotēkas, bet drīzāk augsta līmeņa, no valodas neatkarīgi plāni, lai risinātu atkārtotas problēmas programmatūras arhitektūrā.

JavaScript izstrādātājiem dizaina rakstu izpratne un pielietošana ir svarīgāka nekā jebkad agrāk. Lietojumprogrammām kļūstot arvien sarežģītākām, sākot no komplicētiem priekšgala (front-end) ietvariem līdz jaudīgiem aizmugursistēmas (backend) pakalpojumiem Node.js, stabils arhitektūras pamats nav apspriežams. Dizaina raksti nodrošina šo pamatu, piedāvājot praksē pārbaudītus risinājumus, kas veicina vāju sasaisti, atbildību nodalīšanu un koda atkārtotu izmantošanu.

Šī visaptverošā rokasgrāmata jūs iepazīstinās ar trim fundamentālām dizaina rakstu kategorijām, sniedzot skaidrus paskaidrojumus un praktiskus, mūsdienu JavaScript (ES6+) ieviešanas piemērus. Mūsu mērķis ir sniegt jums zināšanas, lai noteiktu, kuru rakstu izmantot konkrētai problēmai un kā to efektīvi ieviest savos projektos.

Trīs Dizaina Rakstu Pīlāri

Dizaina rakstus parasti iedala trīs galvenajās grupās, no kurām katra risina atšķirīgu arhitektūras izaicinājumu kopumu:

Iedziļināsimies katrā kategorijā ar praktiskiem piemēriem.


Radīšanas Raksti: Objektu Radīšanas Apgūšana

Radīšanas raksti nodrošina dažādus objektu radīšanas mehānismus, kas palielina elastību un esošā koda atkārtotu izmantošanu. Tie palīdz atsaistīt sistēmu no tā, kā tās objekti tiek radīti, sastādīti un attēloti.

Singletona Raksts

Koncepcija: Singletona raksts nodrošina, ka klasei ir tikai viena instance, un nodrošina vienu, globālu piekļuves punktu tai. Jebkurš mēģinājums izveidot jaunu instanci atgriezīs sākotnējo.

Biežākie lietošanas gadījumi: Šis raksts ir noderīgs koplietojamo resursu vai stāvokļa pārvaldībai. Piemēri ietver vienotu datubāzes savienojumu pūlu, globālu konfigurācijas pārvaldnieku vai reģistrēšanas (logging) pakalpojumu, kam jābūt vienotam visā lietojumprogrammā.

Ieviešana JavaScript: Mūsdienu JavaScript, īpaši ar ES6 klasēm, padara Singletona ieviešanu vienkāršu. Mēs varam izmantot statisku īpašību klasē, lai uzglabātu vienīgo instanci.

Piemērs: Reģistrēšanas pakalpojuma Singleton

class Logger { constructor() { if (Logger.instance) { return Logger.instance; } this.logs = []; Logger.instance = this; } log(message) { const timestamp = new Date().toISOString(); this.logs.push({ message, timestamp }); console.log(`${timestamp} - ${message}`); } getLogCount() { return this.logs.length; } } // Tiek izsaukts atslēgvārds 'new', bet konstruktora loģika nodrošina vienu instanci. const logger1 = new Logger(); const logger2 = new Logger(); console.log("Vai reģistrētāji ir viena un tā pati instance?", logger1 === logger2); // true logger1.log("Pirmais ziņojums no logger1."); logger2.log("Otrais ziņojums no logger2."); console.log("Kopējais žurnālu skaits:", logger1.getLogCount()); // 2

Plusi un Mīnusi:

Fabrikas Raksts

Koncepcija: Fabrikas raksts nodrošina saskarni objektu radīšanai superklasē, bet ļauj apakšklasēm mainīt radāmo objektu tipu. Būtība ir izmantot īpašu "fabrikas" metodi vai klasi, lai radītu objektus, nenorādot to konkrētās klases.

Biežākie lietošanas gadījumi: Kad jums ir klase, kas nevar paredzēt, kāda tipa objektus tai ir jārada, vai kad vēlaties nodrošināt savas bibliotēkas lietotājiem veidu, kā radīt objektus, viņiem nezinot iekšējās ieviešanas detaļas. Biežs piemērs ir dažādu tipu lietotāju (administrators, dalībnieks, viesis) radīšana, pamatojoties uz parametru.

Ieviešana JavaScript:

Piemērs: Lietotāju Fabrika

class RegularUser { constructor(name) { this.name = name; this.role = 'Regular'; } viewDashboard() { console.log(`${this.name} skatās lietotāja paneli.`); } } class AdminUser { constructor(name) { this.name = name; this.role = 'Admin'; } viewDashboard() { console.log(`${this.name} skatās administratora paneli ar pilnām tiesībām.`); } } class UserFactory { static createUser(type, name) { switch (type.toLowerCase()) { case 'admin': return new AdminUser(name); case 'regular': return new RegularUser(name); default: throw new Error('Norādīts nederīgs lietotāja tips.'); } } } const admin = UserFactory.createUser('admin', 'Alise'); const regularUser = UserFactory.createUser('regular', 'Bobs'); admin.viewDashboard(); // Alise skatās administratora paneli... regularUser.viewDashboard(); // Bobs skatās lietotāja paneli. console.log(admin.role); // Admin console.log(regularUser.role); // Regular

Plusi un Mīnusi:

Prototipa Raksts

Koncepcija: Prototipa raksts ir par jaunu objektu radīšanu, kopējot esošu objektu, kas pazīstams kā "prototips". Tā vietā, lai veidotu objektu no nulles, jūs izveidojat iepriekš konfigurēta objekta klonu. Tas ir fundamentāli tam, kā pats JavaScript darbojas, izmantojot prototipu mantošanu.

Biežākie lietošanas gadījumi: Šis raksts ir noderīgs, ja objekta radīšanas izmaksas ir dārgākas vai sarežģītākas nekā esošā objekta kopēšana. To izmanto arī, lai radītu objektus, kuru tips tiek norādīts izpildes laikā.

Ieviešana JavaScript: JavaScript ir iebūvēts atbalsts šim rakstam, izmantojot `Object.create()`.

Piemērs: Klonējams transportlīdzekļa prototips

const vehiclePrototype = { init: function(model) { this.model = model; }, getModel: function() { return `Šī transportlīdzekļa modelis ir ${this.model}`; } }; // Izveido jaunu auto objektu, pamatojoties uz transportlīdzekļa prototipu const car = Object.create(vehiclePrototype); car.init('Ford Mustang'); console.log(car.getModel()); // Šī transportlīdzekļa modelis ir Ford Mustang // Izveido citu objektu, kravas automašīnu const truck = Object.create(vehiclePrototype); truck.init('Tesla Cybertruck'); console.log(truck.getModel()); // Šī transportlīdzekļa modelis ir Tesla Cybertruck

Plusi un Mīnusi:


Strukturālie Raksti: Koda Saprātīga Salikšana

Strukturālie raksti ir par to, kā objektus un klases var apvienot, lai veidotu lielākas, sarežģītākas struktūras. Tie koncentrējas uz struktūras vienkāršošanu un attiecību identificēšanu.

Adaptera Raksts

Koncepcija: Adaptera raksts darbojas kā tilts starp divām nesaderīgām saskarnēm. Tas ietver vienu klasi (adapteri), kas apvieno neatkarīgu vai nesaderīgu saskarņu funkcionalitātes. Iedomājieties to kā strāvas adapteri, kas ļauj pievienot ierīci ārzemju elektrības rozetei.

Biežākie lietošanas gadījumi: Jaunas trešās puses bibliotēkas integrēšana ar esošu lietojumprogrammu, kas sagaida citu API, vai veca koda pielāgošana darbam ar modernu sistēmu, nepārrakstot veco kodu.

Ieviešana JavaScript:

Piemērs: Jauna API pielāgošana vecai saskarnei

// Vecā, esošā saskarne, ko izmanto mūsu lietojumprogramma class OldCalculator { operation(term1, term2, operation) { switch (operation) { case 'add': return term1 + term2; case 'sub': return term1 - term2; default: return NaN; } } } // Jaunā, spožā bibliotēka ar atšķirīgu saskarni class NewCalculator { add(term1, term2) { return term1 + term2; } subtract(term1, term2) { return term1 - term2; } } // Adaptera klase class CalculatorAdapter { constructor() { this.calculator = new NewCalculator(); } operation(term1, term2, operation) { switch (operation) { case 'add': // Pielāgo izsaukumu jaunajai saskarnei return this.calculator.add(term1, term2); case 'sub': return this.calculator.subtract(term1, term2); default: return NaN; } } } // Klienta kods tagad var izmantot adapteri, it kā tas būtu vecais kalkulators const oldCalc = new OldCalculator(); console.log("Vecā kalkulatora rezultāts:", oldCalc.operation(10, 5, 'add')); // 15 const adaptedCalc = new CalculatorAdapter(); console.log("Adaptētā kalkulatora rezultāts:", adaptedCalc.operation(10, 5, 'add')); // 15

Plusi un Mīnusi:

Dekoratora Raksts

Koncepcija: Dekoratora raksts ļauj dinamiski pievienot objektam jaunas uzvedības vai atbildības, nemainot tā sākotnējo kodu. Tas tiek panākts, ietinot sākotnējo objektu īpašā "dekoratora" objektā, kas satur jauno funkcionalitāti.

Biežākie lietošanas gadījumi: Funkciju pievienošana lietotāja saskarnes komponentam, lietotāja objekta papildināšana ar atļaujām vai reģistrēšanas/kešošanas uzvedības pievienošana pakalpojumam. Tā ir elastīga alternatīva apakšklašu veidošanai.

Ieviešana JavaScript: Funkcijas JavaScript ir pirmās klases pilsoņi, kas atvieglo dekoratoru ieviešanu.

Piemērs: Kafijas pasūtījuma dekorēšana

// Pamatkomponents class SimpleCoffee { getCost() { return 10; } getDescription() { return 'Vienkārša kafija'; } } // Dekorators 1: Piens function MilkDecorator(coffee) { const originalCost = coffee.getCost(); const originalDescription = coffee.getDescription(); coffee.getCost = function() { return originalCost + 2; }; coffee.getDescription = function() { return `${originalDescription}, ar pienu`; }; return coffee; } // Dekorators 2: Cukurs function SugarDecorator(coffee) { const originalCost = coffee.getCost(); const originalDescription = coffee.getDescription(); coffee.getCost = function() { return originalCost + 1; }; coffee.getDescription = function() { return `${originalDescription}, ar cukuru`; }; return coffee; } // Izveidosim un dekorēsim kafiju let myCoffee = new SimpleCoffee(); console.log(myCoffee.getCost(), myCoffee.getDescription()); // 10, Vienkārša kafija myCoffee = MilkDecorator(myCoffee); console.log(myCoffee.getCost(), myCoffee.getDescription()); // 12, Vienkārša kafija, ar pienu myCoffee = SugarDecorator(myCoffee); console.log(myCoffee.getCost(), myCoffee.getDescription()); // 13, Vienkārša kafija, ar pienu, ar cukuru

Plusi un Mīnusi:

Fasādes Raksts

Koncepcija: Fasādes raksts nodrošina vienkāršotu, augsta līmeņa saskarni sarežģītai klašu, bibliotēku vai API apakšsistēmai. Tas slēpj pamatā esošo sarežģītību un padara apakšsistēmu vieglāk lietojamu.

Biežākie lietošanas gadījumi: Vienkārša API izveide sarežģītam darbību kopumam, piemēram, e-komercijas norēķinu procesam, kas ietver krājumu, maksājumu un piegādes apakšsistēmas. Cits piemērs ir viena metode, lai startētu tīmekļa lietojumprogrammu, kas iekšēji konfigurē serveri, datubāzi un starpprogrammatūru (middleware).

Ieviešana JavaScript:

Piemērs: Hipotēkas pieteikuma fasāde

// Sarežģītas apakšsistēmas class BankService { verify(name, amount) { console.log(`Pārbauda pietiekamus līdzekļus ${name} summai ${amount}`); return amount < 100000; } } class CreditHistoryService { get(name) { console.log(`Pārbauda kredītvēsturi ${name}`); // Simulē labu kredītreitingu return true; } } class BackgroundCheckService { run(name) { console.log(`Veic fona pārbaudi ${name}`); return true; } } // Fasāde class MortgageFacade { constructor() { this.bank = new BankService(); this.credit = new CreditHistoryService(); this.background = new BackgroundCheckService(); } applyFor(name, amount) { console.log(`--- Piesakās hipotēkai ${name} ---`); const isEligible = this.bank.verify(name, amount) && this.credit.get(name) && this.background.run(name); const result = isEligible ? 'Apstiprināts' : 'Noraidīts'; console.log(`--- Pieteikuma rezultāts ${name}: ${result} ---\n`); return result; } } // Klienta kods mijiedarbojas ar vienkāršo fasādi const mortgage = new MortgageFacade(); mortgage.applyFor('Jānis Bērziņš', 75000); // Apstiprināts mortgage.applyFor('Anna Liepiņa', 150000); // Noraidīts

Plusi un Mīnusi:


Uzvedības Raksti: Objektu Komunikācijas Organizēšana

Uzvedības raksti ir par to, kā objekti savstarpēji komunicē, koncentrējoties uz atbildības piešķiršanu un efektīvu mijiedarbības pārvaldību.

Novērotāja Raksts

Koncepcija: Novērotāja raksts definē viena-pret-daudziem atkarību starp objektiem. Kad viens objekts ("subjekts" jeb "novērojamais") maina savu stāvokli, visi tā atkarīgie objekti ("novērotāji") tiek automātiski informēti un atjaunināti.

Biežākie lietošanas gadījumi: Šis raksts ir notikumu vadītas programmēšanas (event-driven programming) pamats. To plaši izmanto lietotāja saskarņu izstrādē (DOM notikumu klausītāji), stāvokļa pārvaldības bibliotēkās (piemēram, Redux vai Vuex) un ziņojumapmaiņas sistēmās.

Ieviešana JavaScript:

Piemērs: Ziņu aģentūra un abonenti

// Subjekts (Novērojamais) class NewsAgency { constructor() { this.subscribers = []; } subscribe(subscriber) { this.subscribers.push(subscriber); console.log(`${subscriber.name} ir abonējis.`); } unsubscribe(subscriber) { this.subscribers = this.subscribers.filter(sub => sub !== subscriber); console.log(`${subscriber.name} ir anulējis abonementu.`); } notify(news) { console.log(`--- ZIŅU AĢENTŪRA: Izplata ziņas: "${news}" ---`); this.subscribers.forEach(subscriber => subscriber.update(news)); } } // Novērotājs class Subscriber { constructor(name) { this.name = name; } update(news) { console.log(`${this.name} saņēma jaunākās ziņas: "${news}"`); } } const agency = new NewsAgency(); const sub1 = new Subscriber('Lasītājs A'); const sub2 = new Subscriber('Lasītājs B'); const sub3 = new Subscriber('Lasītājs C'); agency.subscribe(sub1); agency.subscribe(sub2); agency.notify('Globālie tirgi ir augšupejā!'); agency.subscribe(sub3); agency.unsubscribe(sub2); agency.notify('Paziņots par jaunu tehnoloģiju sasniegumu!');

Plusi un Mīnusi:

Stratēģijas Raksts

Koncepcija: Stratēģijas raksts definē savstarpēji aizvietojamu algoritmu saimi un katru no tiem iekapsulē savā klasē. Tas ļauj algoritmu izvēlēties un mainīt izpildes laikā, neatkarīgi no klienta, kas to izmanto.

Biežākie lietošanas gadījumi: Dažādu šķirošanas algoritmu, validācijas noteikumu vai piegādes izmaksu aprēķināšanas metožu ieviešana e-komercijas vietnē (piemēram, fiksētā likme, pēc svara, pēc galamērķa).

Ieviešana JavaScript:

Piemērs: Piegādes izmaksu aprēķināšanas stratēģija

// Konteksts class Shipping { constructor() { this.company = null; } setStrategy(company) { this.company = company; console.log(`Piegādes stratēģija iestatīta uz: ${company.constructor.name}`); } calculate(pkg) { if (!this.company) { throw new Error('Piegādes stratēģija nav iestatīta.'); } return this.company.calculate(pkg); } } // Stratēģijas class FedExStrategy { calculate(pkg) { // Sarežģīts aprēķins, pamatojoties uz svaru utt. const cost = pkg.weight * 2.5 + 5; console.log(`FedEx izmaksas pakai ar svaru ${pkg.weight}kg ir $${cost}`); return cost; } } class UPSStrategy { calculate(pkg) { const cost = pkg.weight * 2.1 + 4; console.log(`UPS izmaksas pakai ar svaru ${pkg.weight}kg ir $${cost}`); return cost; } } class PostalServiceStrategy { calculate(pkg) { const cost = pkg.weight * 1.8; console.log(`Pasta pakalpojuma izmaksas pakai ar svaru ${pkg.weight}kg ir $${cost}`); return cost; } } const shipping = new Shipping(); const packageA = { from: 'New York', to: 'London', weight: 5 }; shipping.setStrategy(new FedExStrategy()); shipping.calculate(packageA); shipping.setStrategy(new UPSStrategy()); shipping.calculate(packageA); shipping.setStrategy(new PostalServiceStrategy()); shipping.calculate(packageA);

Plusi un Mīnusi:


Mūsdienu Raksti un Arhitektūras Apsvērumi

Kaut arī klasiskie dizaina raksti ir mūžīgi, JavaScript ekosistēma ir attīstījusies, radot modernas interpretācijas un liela mēroga arhitektūras rakstus, kas ir būtiski mūsdienu izstrādātājiem.

Moduļa Raksts

Moduļa raksts bija viens no visizplatītākajiem rakstiem pirms-ES6 JavaScript, lai izveidotu privātus un publiskus tvērumus (scopes). Tas izmanto noslēgumus (closures), lai iekapsulētu stāvokli un uzvedību. Mūsdienās šo rakstu lielā mērā ir aizstājuši natīvie ES6 Moduļi (`import`/`export`), kas nodrošina standartizētu, uz failiem balstītu moduļu sistēmu. ES6 moduļu izpratne ir fundamentāla jebkuram mūsdienu JavaScript izstrādātājam, jo tie ir standarts koda organizēšanai gan priekšgala, gan aizmugursistēmas lietojumprogrammās.

Arhitektūras Raksti (MVC, MVVM)

Ir svarīgi atšķirt dizaina rakstus no arhitektūras rakstiem. Kamēr dizaina raksti risina specifiskas, lokalizētas problēmas, arhitektūras raksti nodrošina augsta līmeņa struktūru visai lietojumprogrammai.

Strādājot ar ietvariem kā React, Vue vai Angular, jūs jau pēc būtības izmantojat šos arhitektūras rakstus, bieži apvienojot tos ar mazākiem dizaina rakstiem (piemēram, Novērotāja rakstu stāvokļa pārvaldībai), lai veidotu stabilas lietojumprogrammas.


Noslēgums: Rakstu Gudra Izmantošana

JavaScript dizaina raksti nav stingri noteikumi, bet gan spēcīgi rīki izstrādātāja arsenālā. Tie pārstāv programmatūras inženierijas kopienas kolektīvo gudrību, piedāvājot elegantus risinājumus bieži sastopamām problēmām.

Galvenais, lai tos apgūtu, nav iegaumēt katru rakstu, bet gan saprast problēmu, ko katrs no tiem risina. Kad jūs saskaraties ar izaicinājumu savā kodā — vai tā būtu cieša sasaiste, sarežģīta objektu radīšana vai neelastīgi algoritmi — jūs varat ķerties pie atbilstošā raksta kā labi definēta risinājuma.

Mūsu pēdējais padoms ir šāds: Sāciet, rakstot vienkāršāko kodu, kas darbojas. Kad jūsu lietojumprogramma attīstās, pārveidojiet (refactor) savu kodu, virzoties uz šiem rakstiem tur, kur tie dabiski iederas. Nepiespiediet rakstu tur, kur tas nav nepieciešams. Pielietojot tos apdomīgi, jūs rakstīsiet kodu, kas ir ne tikai funkcionāls, bet arī tīrs, mērogojams un patīkami uzturams gadiem ilgi.