Sobes.tech
Middle+

Porozprávaj mi o vzorec dizajnu, ktorý si použil vo svojom vývoji.

sobes.tech AI

Odpoveď od AI

Použil som nasledujúce vzory návrhu:

  • MVC (Model-View-Controller): Rozdelenie logiky aplikácie. Model spravuje údaje, Zobrazenie je zodpovedné za zobrazenie a Kontrolér spracováva interakciu používateľa a aktualizuje Model alebo Zobrazenie. Používal v Angular, kde čiastočne implementujú túto ideológiu.

  • MVVM (Model-View-ViewModel): Podobné MVC, ale zavádza ViewModel ako sprostredkovateľa medzi Zobrazením a Modelom. ViewModel obsahuje biznis logiku pre zobrazovanie dát a spracovanie akcií používateľa. Aktívne som používal s React a Vuex (Vue), kde je stav aplikácie centralizovaný.

    // Príklad reaktivity v React s použitím useState
    import React, { useState } from 'react';
    
    function Counter() {
      const [count, setCount] = useState(0); // useState je časťou MVVM mechanizmu
    
      const increment = () => {
        setCount(count + 1); // Aktualizácia stavu cez setter
      };
    
      return (
        <div>
          <p>Počet: {count}</p> {/* Zobrazenie stavu */}
          <button onClick={increment}>Zvýšiť</button> {/* Akcia ovplyvňujúca stav */}
        </div>
      );
    }
    
  • Komponentný vzor: Rozdelenie používateľského rozhrania na nezávislé, znovupoužiteľné komponenty. Každá komponenta enkapsuluje svoju logiku, štruktúru a štýly. Je základom moderných rámcov ako React, Vue a Angular.

    // Príklad jednoduchého React komponentu
    function Button(props) {
      return (
        <button className="my-button" onClick={props.onClick}>
          {props.label}
        </button>
      );
    }
    
  • Adapter (Prispôsobovač): Pretvára rozhranie jednej triedy na inú, ktorú očakávajú klienti. Umožňuje pracovať s triedami s nekompatibilnými rozhraniami. Používal na integráciu externých knižníc alebo API s rôznymi podpismi metód.

    // Príklad adaptéra na prácu s rôznymi API klientmi
    class OldApi {
      getDataOld(id) {
        console.log(`Získavanie dát z Old API pre id ${id}`);
        return { id: id, name: `Položka ${id}` };
      }
    }
    
    class NewApi {
      fetchDataNew(itemId) {
        console.log(`Načítanie dát z New API pre položku id ${itemId}`);
        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) {
          // Transformácia dát z nového formátu
          const newData = this.apiClient.fetchDataNew(id);
          return { id: newData.itemId, name: newData.label };
        }
        throw new Error("Nepodporovaný API klient");
      }
    }
    
    const oldApiAdapter = new ApiAdapter(new OldApi());
    console.log(oldApiAdapter.getData(1));
    
    const newApiAdapter = new ApiAdapter(new NewApi());
    console.log(newApiAdapter.getData(2));
    
  • Iterátor (Iterator): Poskytuje spôsob sekvenčného prístupu k prvkom zloženého objektu, neodkrývajúc jeho vnútorné zobrazenie. Používa sa v cykloch (for...of) a metódach polí (forEach, map, filter).

    // Príklad použitia iterátora v JavaScripte
    const numbers = [1, 2, 3, 4, 5];
    
    // Explicitné získanie iterátora
    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 }
    
    // Použitie iterátora v for...of
    for (const number of numbers) {
      console.log(number);
    }
    
  • Dekorátor (Decorator): Dynamicky pridáva nové povinnosti objektu, umožňujúc rozšíriť funkcionalitu objektu bez zmeny jeho štruktúry. Používal v podobe HOC (Higher-Order Components) v React alebo dekorátorov v Angular/TypeScript.

    // Príklad Higher-Order Component (HOC) v React
    function withLogging(WrappedComponent) {
      return function WithLogging(props) {
        console.log(`Komponent ${WrappedComponent.name} renderovaný s props:`, props);
        return <WrappedComponent {...props} />;
      };
    }
    
    // Použitie HOC
    const EnhancedButton = withLogging(Button);
    
    // Použitie vylepšenej komponenty
    // <EnhancedButton label="Klikni" onClick={() => console.log('Kliknuto!')} />
    
  • Orol (Singleton): Zaručuje, že má trieda iba jeden inštanciu, a poskytuje globálny prístup k nej. Používal na správu globálneho stavu aplikácie alebo na vytvorenie jedinečného inštancie služby (napr. služby na logovanie, konfiguráciu).

    // Príklad vzoru Orol
    class ConfigManager {
      constructor() {
        if (ConfigManager.instance) {
          return ConfigManager.instance;
        }
        this.settings = {}; // Inicializácia nastavení
        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 (tá istá inštancia)
    
    config1.setSetting('apiUrl', 'https://api.example.com');
    console.log(config2.getSetting('apiUrl')); // https://api.example.com
    
  • Fabrika metóda (Factory Method): Definuje rozhranie pre tvorbu objektu, ale umožňuje podtriedam rozhodnúť, ktorý objekt vytvoriť. Používal na tvorbu rôznych typov prvkov používateľského rozhrania alebo objektov na základe konfigurácie.

  • Stratégia (Strategy): Definuje rodinu algoritmov, enkapsuluje každý z nich a robí ich zameniteľnými. Umožňuje algoritmu meniť sa nezávisle od klientov, ktorí ho používajú. Používal na implementáciu rôznych prístupov k triedeniu dát, validácii formulárov alebo spracovaniu udalostí.

Použitie týchto vzorov pomáhalo vytvárať štruktúrovanejší, modulárnejší, testovateľnejší a udržiavateľnejší kód.