Sobes.tech
Middle+

Erzählen Sie mir vom Designmuster, das Sie in Ihrer Entwicklung verwendet haben.

sobes.tech KI

Antwort von AI

Ich habe die folgenden Entwurfsmuster verwendet:

  • MVC (Model-View-Controller): Trennung der Anwendungslogik. Das Modell verwaltet die Daten, die Ansicht ist für die Darstellung verantwortlich, und der Controller verarbeitet die Benutzerinteraktion und aktualisiert das Modell oder die Ansicht. Ich habe es in Angular angewendet, wo Komponenten diese Ideologie teilweise umsetzen.

  • MVVM (Model-View-ViewModel): Ähnlich wie MVC, aber führt das ViewModel als Vermittler zwischen Ansicht und Modell ein. Das ViewModel enthält die Geschäftslogik zur Anzeige der Daten und zur Verarbeitung von Benutzeraktionen. Ich habe es aktiv mit React und Vuex (Vue) genutzt, wo der Anwendungszustand zentral verwaltet wird.

    // Beispiel für Reaktivität in React mit useState
    import React, { useState } from 'react';
    
    function Counter() {
      const [count, setCount] = useState(0); // useState ist Teil des MVVM-Mechanismus
    
      const increment = () => {
        setCount(count + 1); // Zustand-Update über den Setter
      };
    
      return (
        <div>
          <p>Zähler: {count}</p> {/* Anzeige des Zustands */}
          <button onClick={increment}>Inkrementieren</button> {/* Aktion, die den Zustand beeinflusst */}
        </div>
      );
    }
    
  • Komponentenmuster: Unterteilung der Benutzeroberfläche in unabhängige, wiederverwendbare Komponenten. Jede Komponente kapselt ihre Logik, Markup und Stile. Es bildet die Grundlage moderner Frameworks wie React, Vue und Angular.

    // Beispiel für eine einfache React-Komponente
    function Button(props) {
      return (
        <button className="my-button" onClick={props.onClick}>
          {props.label}
        </button>
      );
    }
    
  • Adapter (Adapter): Wandelt die Schnittstelle einer Klasse in eine andere um, die von den Kunden erwartet wird. Erlaubt die Zusammenarbeit von Klassen mit inkompatiblen Schnittstellen. Ich habe es zur Integration externer Bibliotheken oder APIs mit unterschiedlichen Methodensignaturen verwendet.

    // Beispiel für einen Adapter zur Arbeit mit verschiedenen API-Clients
    class OldApi {
      getDataOld(id) {
        console.log(`Daten von Old API für id ${id} abrufen`);
        return { id: id, name: `Item ${id}` };
      }
    }
    
    class NewApi {
      fetchDataNew(itemId) {
        console.log(`Daten von New API für Artikel-ID ${itemId} abrufen`);
        return { itemId: itemId, label: `Produkt ${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) {
          // Transformation der Daten aus dem neuen Format
          const newData = this.apiClient.fetchDataNew(id);
          return { id: newData.itemId, name: newData.label };
        }
        throw new Error("Nicht unterstützter 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): Bietet eine Möglichkeit, sequenziell auf die Elemente eines zusammengesetzten Objekts zuzugreifen, ohne dessen interne Darstellung offenzulegen. Wird in Schleifen (for...of) und Array-Methoden (forEach, map, filter) verwendet.

    // Beispiel für die Verwendung eines Iterators in JavaScript
    const numbers = [1, 2, 3, 4, 5];
    
    // Explizite Iterator-Erstellung
    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 }
    
    // Verwendung des Iterators in for...of
    for (const number of numbers) {
      console.log(number);
    }
    
  • Decorator (Dekorateur): Fügt einem Objekt dynamisch neue Verantwortlichkeiten hinzu, um dessen Funktionalität zu erweitern, ohne seine Struktur zu verändern. Ich habe es in Form von HOC (Higher-Order Components) in React oder Dekoratoren in Angular/TypeScript verwendet.

    // Beispiel für einen HOC in React
    function withLogging(WrappedComponent) {
      return function WithLogging(props) {
        console.log(`Komponente ${WrappedComponent.name} gerendert mit props:`, props);
        return <WrappedComponent {...props} />;
      };
    }
    
    // Verwendung des HOC
    const EnhancedButton = withLogging(Button);
    
    // Verwendung der verbesserten Komponente
    // <EnhancedButton label="Klick mich" onClick={() => console.log('Geklickt!')} />
    
  • Singleton (Singleton): Garantiert, dass eine Klasse nur eine Instanz hat, und stellt einen globalen Zugriffspunkt darauf bereit. Ich habe es zur Verwaltung des globalen Zustands der Anwendung oder zur Erstellung einer einzigen Instanz eines Dienstes (z.B. Logging-Service, Konfiguration) verwendet.

    // Beispiel für das Singleton-Muster
    class ConfigManager {
      constructor() {
        if (ConfigManager.instance) {
          return ConfigManager.instance;
        }
        this.settings = {}; // Initialisierung der Einstellungen
        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 (gleiche Instanz)
    
    config1.setSetting('apiUrl', 'https://api.beispiel.com');
    console.log(config2.getSetting('apiUrl')); // https://api.beispiel.com
    
  • Fabrikmethode (Factory Method): Definiert eine Schnittstelle zur Objekterstellung, lässt aber Unterklassen entscheiden, welche Klasse instanziiert wird. Ich habe es verwendet, um verschiedene Arten von UI-Elementen oder Objekten basierend auf der Konfiguration zu erstellen.

  • Strategie (Strategy): Definiert eine Familie von Algorithmen, kapselt jeden und macht sie austauschbar. Ermöglicht es, den Algorithmus unabhängig von den Clients, die ihn verwenden, zu variieren. Ich habe es genutzt, um verschiedene Ansätze für das Sortieren von Daten, die Validierung von Formularen oder die Ereignisbehandlung zu implementieren.

Der Einsatz dieser Muster half dabei, einen strukturierteren, modulareren, testbaren und wartbaren Code zu erstellen.