slogan3

JavaScript Gebruik van Design Patterns voor Schaalbare Applicaties

description

Met deze prompt leer je de juiste design patterns toepassen in JavaScript waardoor je applicaties beter schaalbaar en onderhoudbaar worden. Het helpt je complexe code overzichtelijk te houden en bevordert hergebruik en consistente architectuur, wat lastig is zonder gerichte kennis van patronen.

prompt

Leg me uit hoe ik verschillende design patterns kan toepassen in mijn JavaScript-project om de code beter schaalbaar en onderhoudbaar te mak ...

try_prompt

generate_helper
disclaimerOnPageApi

ai_answers

provider: openai
model: gpt-4.1-nano
Natuurlijk! Het toepassen van design patterns kan je helpen om je JavaScript-code beter schaalbaar en onderhoudbaar te maken, vooral bij complexe projecten zoals een webshop met winkelwagen en productfilters. Hier bespreek ik enkele relevante patronen en geef ik voorbeelden die aansluiten bij jouw situatie. 1. Singleton Pattern **Wat:** Zorgt dat een klasse slechts één instantie heeft en biedt een globale toegangspoort. **Toepassing:** Beheer de winkelwagen als een enkele instantie zodat alle onderdelen van de app dezelfde winkelwagen gebruiken. **Voorbeeld:** ```javascript const ShoppingCart = (function() { let instance; function init() { let items = []; return { addItem: function(product) { items.push(product); }, getItems: function() { return items; }, clear: function() { items = []; } }; } return { getInstance: function() { if (!instance) { instance = init(); } return instance; } }; })(); // Gebruik: const cart = ShoppingCart.getInstance(); cart.addItem({ id: 1, name: 'Product A', price: 10 }); ``` 2. Factory Pattern **Wat:** Maakt objectcreatie flexibeler door een centrale factory te gebruiken. **Toepassing:** Voor het maken van verschillende soorten filters (bijvoorbeeld prijsfilter, categoriefilter). **Voorbeeld:** ```javascript class PriceFilter { constructor(maxPrice) { this.maxPrice = maxPrice; } apply(products) { return products.filter(p => p.price <= this.maxPrice); } } class CategoryFilter { constructor(category) { this.category = category; } apply(products) { return products.filter(p => p.category === this.category); } } class FilterFactory { static createFilter(type, criteria) { switch(type) { case 'price': return new PriceFilter(criteria); case 'category': return new CategoryFilter(criteria); default: throw new Error('Onbekend filtertype'); } } } // Gebruik: const filter = FilterFactory.createFilter('price', 50); const gefilterdeProducten = filter.apply(allProducts); ``` 3. Observer Pattern **Wat:** Biedt een manier om objecten te laten reageren op veranderingen in andere objecten. **Toepassing:** Voor het bijwerken van de productlijst wanneer filters wijzigen of de winkelwagen wordt aangepast. **Voorbeeld:** ```javascript class Observable { constructor() { this.observers = []; } subscribe(observer) { this.observers.push(observer); } notify(data) { this.observers.forEach(obs => obs.update(data)); } } class ProductFilter extends Observable { constructor() { super(); this.criteria = {}; } setCriteria(criteria) { this.criteria = criteria; this.notify(this.criteria); } } // Observer class ProductList { update(criteria) { // Pas productlijst aan op basis van criteria console.log('Productlijst wordt bijgewerkt met:', criteria); } } // Gebruik: const filter = new ProductFilter(); const productList = new ProductList(); filter.subscribe(productList); filter.setCriteria({ category: 'kleding', priceMax: 100 }); ``` 4. Strategy Pattern **Wat:** Definieert een familie van algoritmen, kapselt ze in en maakt ze verwisselbaar. **Toepassing:** Voor het bepalen van de manier waarop filters worden toegepast, bijvoorbeeld sorteren of filteren. **Voorbeeld:** ```javascript class SortStrategy { sort(products) { throw new Error('Method moet worden geïmplementeerd'); } } class PriceSortStrategy extends SortStrategy { sort(products) { return products.slice().sort((a, b) => a.price - b.price); } } class NameSortStrategy extends SortStrategy { sort(products) { return products.slice().sort((a, b) => a.name.localeCompare(b.name)); } } class ProductSorter { constructor(strategy) { this.strategy = strategy; } setStrategy(strategy) { this.strategy = strategy; } sort(products) { return this.strategy.sort(products); } } // Gebruik: const sorter = new ProductSorter(new PriceSortStrategy()); const gesorteerdeProducten = sorter.sort(allProducts); ``` **Samenvatting:** - Gebruik Singleton voor gedeelde data (winkelwagen). - Gebruik Factory voor het maken van verschillende filters. - Gebruik Observer voor het reageren op wijzigingen (filters, winkelwagen). - Gebruik Strategy voor het flexibel toepassen van sorteer- of filteralgoritmen. Door deze patronen strategisch te gebruiken, wordt je code modulairder, makkelijker te onderhouden en uit te breiden.
provider: deepseek
model: deepseek-chat
Zeker! Hier leg ik uit hoe je design patterns kunt toepassen in een JavaScript-webshop voor betere schaalbaarheid en onderhoudbaarheid. ### 1. **Singleton Pattern** - Voor de winkelwagen **Doel:** Zorgen dat er maar één instantie van de winkelwagen bestaat. ```javascript class Winkelwagen { constructor() { if (Winkelwagen.instance) { return Winkelwagen.instance; } this.producten = []; this.totaal = 0; Winkelwagen.instance = this; } voegToe(product) { this.producten.push(product); this.berekenTotaal(); } verwijder(productId) { this.producten = this.producten.filter(p => p.id !== productId); this.berekenTotaal(); } berekenTotaal() { this.totaal = this.producten.reduce((acc, product) => acc + product.prijs, 0); } } // Gebruik: const winkelwagen = new Winkelwagen(); Object.freeze(winkelwagen); // Voorkomt aanpassingen ``` ### 2. **Observer Pattern** - Voor real-time updates **Doel:** Automatisch updates doorgeven bij wijzigingen in de winkelwagen. ```javascript class Observable { constructor() { this.observers = []; } subscribe(observer) { this.observers.push(observer); } unsubscribe(observer) { this.observers = this.observers.filter(obs => obs !== observer); } notify(data) { this.observers.forEach(observer => observer.update(data)); } } class WinkelwagenObserver extends Observable { voegToe(product) { super.notify({ type: 'TOEGEVOEGD', product }); } } // Gebruik: const cartObserver = new WinkelwagenObserver(); cartObserver.subscribe({ update: (data) => { console.log(`Product ${data.product.naam} is toegevoegd`); // Update UI elementen } }); ``` ### 3. **Strategy Pattern** - Voor productfilters **Doel:** Flexibel filtergedrag kunnen wisselen. ```javascript class FilterStrategy { filter(producten) { throw new Error('Moet geïmplementeerd worden'); } } class PrijsFilter extends FilterStrategy { filter(producten, maxPrijs) { return producten.filter(product => product.prijs <= maxPrijs); } } class CategorieFilter extends FilterStrategy { filter(producten, categorie) { return producten.filter(product => product.categorie === categorie); } } class ProductFilter { constructor() { this.strategy = null; } setStrategy(strategy) { this.strategy = strategy; } filter(producten, ...args) { return this.strategy.filter(producten, ...args); } } // Gebruik: const filter = new ProductFilter(); filter.setStrategy(new PrijsFilter()); const gefilterdeProducten = filter.filter(producten, 50); ``` ### 4. **Factory Pattern** - Voor productcreatie **Doel:** Gestandaardiseerde productaanmaak. ```javascript class ProductFactory { createProduct(type, data) { switch(type) { case 'fysiek': return new FysiekProduct(data); case 'digitaal': return new DigitaalProduct(data); default: throw new Error('Onbekend producttype'); } } } class FysiekProduct { constructor(data) { this.type = 'fysiek'; this.voorraad = data.voorraad; // ... andere properties } } ``` ### 5. **Module Pattern** - Voor code-organisatie **Doel:** Code modulair en geïsoleerd houden. ```javascript const ProductModule = (() => { const privateVariabelen = []; const privateFunctie = () => { // Private logica }; return { publicMethod: () => { privateFunctie(); // Publieke interface }, anotherPublicMethod: () => { // Meer publieke functionaliteit } }; })(); ``` ### 6. **Proxy Pattern** - Voor caching en validatie **Doel:** Extra functionaliteit toevoegen zonder bestaande code aan te passen. ```javascript class ProductServiceProxy { constructor(service) { this.service = service; this.cache = new Map(); } haalProducten(opties) { const key = JSON.stringify(opties); if (this.cache.has(key)) { return this.cache.get(key); } const resultaat = this.service.haalProducten(opties); this.cache.set(key, resultaat); return resultaat; } } ``` ### Praktische implementatie in je webshop: ```javascript // Hoofdapplicatie class Webshop { constructor() { this.winkelwagen = new Winkelwagen(); this.filters = new ProductFilter(); this.productService = new ProductServiceProxy(new ProductService()); this.initialiseerEventListeners(); } initialiseerEventListeners() { // Event binding voor filters en winkelwagen } pasFiltersToe(filterType, waarde) { this.filters.setStrategy(this.maakFilterStrategy(filterType)); return this.filters.filter(this.producten, waarde); } } ``` **Voordelen:** - ✅ Makkelijke uitbreiding nieuwe filters - ✅ Losse koppeling tussen componenten - ✅ Herbruikbare code - ✅ Eenvoudig testbaar - ✅ Betere onderhoudbaarheid Start met de patterns die het meeste waarde toevoegen voor jouw specifieke use case en breid geleidelijk uit!