Sobes.tech
Middle+

Vertel me over het ontwerp van patronen dat je hebt gebruikt in je ontwikkeling.

sobes.tech AI

Antwoord van AI

Ik heb de volgende ontwerppatronen gebruikt:

  • MVC (Model-View-Controller): Scheiding van de logica van de applicatie. Het model beheert de gegevens, de View is verantwoordelijk voor de weergave, en de Controller behandelt de interactie van de gebruiker en werkt het Model of de View bij. Toegepast in Angular, waar componenten deze ideologie gedeeltelijk implementeren.

  • MVVM (Model-View-ViewModel): Lijkt op MVC, maar introduceert de ViewModel als tussenpersoon tussen de View en het Model. De ViewModel bevat de bedrijfslogica voor het weergeven van gegevens en het verwerken van gebruikersacties. Actief gebruikt met React en Vuex (Vue), waar de status van de applicatie centraal wordt beheerd.

    // Voorbeeld van reactieve data in React met useState
    import React, { useState } from 'react';
    
    function Counter() {
      const [count, setCount] = useState(0); // deel van het MVVM mechanisme
    
      const increment = () => {
        setCount(count + 1); // status bijwerken via setter
      };
    
      return (
        <div>
          <p>Count: {count}</p> {/* Weergave van de status */}
          <button onClick={increment}>Increment</button> {/* Actie die de status beïnvloedt */}
        </div>
      );
    }
    
  • Component patroon: Verdeling van de gebruikersinterface in onafhankelijke, herbruikbare componenten. Elke component encapsuleert zijn eigen logica, markup en stijlen. De basis van moderne frameworks zoals React, Vue en Angular.

    // Voorbeeld van een eenvoudige React component
    function Button(props) {
      return (
        <button className="my-button" onClick={props.onClick}>
          {props.label}
        </button>
      );
    }
    
  • Adapter (Aansluiting): Transformeert de interface van een klasse naar een andere die door de klanten wordt verwacht. Maakt het mogelijk om klassen met incompatibele interfaces samen te laten werken. Gebruikt voor het integreren van externe bibliotheken of API's met verschillende methodesignaturen.

    // Voorbeeld van een adapter voor werken met verschillende API-clients
    class OldApi {
      getDataOld(id) {
        console.log(`Data ophalen van Old API voor id ${id}`);
        return { id: id, name: `Item ${id}` };
      }
    }
    
    class NewApi {
      fetchDataNew(itemId) {
        console.log(`Data ophalen van New API voor item id ${itemId}`);
        return { itemId: itemId, label: `Product ${itemId}` };
      }
    }
    
    class ApiAdapter {
      constructor(apiClient) {
        this.apiClient = apiClient;
      }
    
      getData(id) {
        if (this.apiClient instanceof OldApi) {
          return this.apiClient.getDataOld(id);
        } else if (this.apiClient instanceof NewApi) {
          const newData = this.apiClient.fetchDataNew(id);
          return { id: newData.itemId, name: newData.label };
        }
        throw new Error("Niet-ondersteunde API-client");
      }
    }
    
    const oldApiAdapter = new ApiAdapter(new OldApi());
    console.log(oldApiAdapter.getData(1));
    
    const newApiAdapter = new ApiAdapter(new NewApi());
    console.log(newApiAdapter.getData(2));
    
  • Iterator (Iterator): Biedt een manier om sequentieel toegang te krijgen tot elementen van een samengesteld object zonder de interne representatie te onthullen. Gebruikt in lussen (for...of) en array-methoden (forEach, map, filter).

    // Voorbeeld van het gebruik van een iterator in JavaScript
    const numbers = [1, 2, 3, 4, 5];
    
    const iterator = numbers[Symbol.iterator]();
    
    console.log(iterator.next()); // { value: 1, done: false }
    console.log(iterator.next()); // { value: 2, done: false }
    // ...
    console.log(iterator.next()); // { value: undefined, done: true }
    
    for (const number of numbers) {
      console.log(number);
    }
    
  • Decorator (Decorator): Voegt dynamisch nieuwe verantwoordelijkheden toe aan een object, waardoor de functionaliteit ervan kan worden uitgebreid zonder de structuur te wijzigen. Gebruikt als HOC (Higher-Order Components) in React of decorateurs in Angular/TypeScript.

    // Voorbeeld van Higher-Order Component (HOC) in React
    function withLogging(WrappedComponent) {
      return function WithLogging(props) {
        console.log(`Component ${WrappedComponent.name} gerenderd met props:`, props);
        return <WrappedComponent {...props} />;
      };
    }
    
    // Toepassing van HOC
    const EnhancedButton = withLogging(Button);
    
    // Gebruik van de verbeterde component
    // <EnhancedButton label="Klik me" onClick={() => console.log('Klik!')} />
    
  • Singleton (Enkelvoud): Garandeert dat een klasse slechts één instantie heeft en biedt een globale toegangspunt tot die instantie. Gebruikt voor het beheren van de globale status van de applicatie of het maken van een enkele instantie van een service (bijvoorbeeld logging of configuratieservice).

    // Voorbeeld van het singleton patroon
    class ConfigManager {
      constructor() {
        if (ConfigManager.instance) {
          return ConfigManager.instance;
        }
        this.settings = {}; // Initialisatie van instellingen
        ConfigManager.instance = this;
      }
    
      setSetting(key, value) {
        this.settings[key] = value;
      }
    
      getSetting(key) {
        return this.settings[key];
      }
    }
    
    const config1 = new ConfigManager();
    const config2 = new ConfigManager();
    
    console.log(config1 === config2); // true (dezelfde instantie)
    
    config1.setSetting('apiUrl', 'https://api.example.com');
    console.log(config2.getSetting('apiUrl')); // https://api.example.com
    
  • Fabriksmethode (Factory Method): Definieert interface voor het maken van een object, maar laat subklassen beslissen welke klasse te maken. Gebruikt voor het maken van verschillende typen UI-elementen of objecten op basis van configuratie.

  • Strategie (Strategy): Definieert een familie van algoritmen, kapselt elk ervan in en maakt ze uitwisselbaar. Hiermee kan het algoritme onafhankelijk van de clients die het gebruiken variëren. Gebruikt voor het implementeren van verschillende benaderingen voor sortering van gegevens, validatie van formulieren of gebeurtenisverwerking.

Het gebruik van deze patronen hielp om meer gestructureerde, modulaire, testbare en onderhoudbare code te creëren.