Mesélj a mintázattervezésről, amit a fejlesztésed során használtál.
sobes.tech MI
Válasz az MI-től
Az alábbi tervezési mintákat használtam:
-
MVC (Model-View-Controller): Az alkalmazás logikájának szétválasztása. A modell kezeli az adatokat, a nézet felelős a megjelenítésért, a vezérlő pedig a felhasználói interakciókat kezeli, és frissíti a modellt vagy a nézetet. Angularban használtam, ahol a komponensek részben valósítják meg ezt az ideológiát.
-
MVVM (Model-View-ViewModel): Hasonló az MVC-hez, de bevezeti a ViewModel-t, mint közvetítőt a nézet és a modell között. A ViewModel tartalmazza az üzleti logikát az adatok megjelenítéséhez és a felhasználói műveletek kezeléséhez. Aktívan használtam React és Vuex (Vue) esetén, ahol az alkalmazás állapota központilag van kezelve.
// Reaktív példa useState használatával import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); // a useState az MVVM mechanizmus része const increment = () => { setCount(count + 1); // állapot frissítése a setterrel }; return ( <div> <p>Szám: {count}</p> {/* állapot megjelenítése */} <button onClick={increment}>Növel</button> {/* művelet, ami befolyásolja az állapotot */} </div> ); } -
Komponens mintázat: A felhasználói felületet független, újra felhasználható komponensekre bontja. Minden komponens inkapszulálja a saját logikáját, szerkezetét és stílusát. Ez a modern keretrendszerek, mint a React, Vue és Angular alapja.
// Egyszerű React komponens példa function Button(props) { return ( <button className="my-button" onClick={props.onClick}> {props.label} </button> ); } -
Adapter (Adapter): Egy osztály interfészét másikra alakítja, amit a kliensek elvárnak. Lehetővé teszi inkompatibilis interfészekkel rendelkező osztályok együttműködését. Harmadik fél könyvtárak vagy API-k integrációjára használtam, különböző metódusszignatúrákkal.
// Adapter példa különböző API-kliensekhez class OldApi { getDataOld(id) { console.log(`Adatok lekérése az Old API-ból, id ${id}`); return { id: id, name: `Tétel ${id}` }; } } class NewApi { fetchDataNew(itemId) { console.log(`Adatok lekérése az Új API-ból, tétel id ${itemId}`); return { itemId: itemId, label: `Termék ${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) { // Az adatok átalakítása az új formátumból const newData = this.apiClient.fetchDataNew(id); return { id: newData.itemId, name: newData.label }; } throw new Error("Nem támogatott API kliens"); } } 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): Lehetővé teszi az elemek sorozatos hozzáférését anélkül, hogy feltárná belső reprezentációját. Használják ciklusokban (
for...of) és tömbmetódusokban (forEach,map,filter).// Iterátor használatának példája JavaScriptben const numbers = [1, 2, 3, 4, 5]; // Közvetlen iterator megszerzése 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 } // Iterator használata for...of ciklusban for (const number of numbers) { console.log(number); } -
Díszítő (Decorator): Dinamikusan ad hozzá új feladatokat egy objektumhoz, lehetővé téve az objektum funkcionalitásának bővítését anélkül, hogy megváltoztatná szerkezetét. Reactben HOC-ként (Higher-Order Components) vagy dekorátorokként Angular/TypeScript környezetben használtam.
// HOC példa Reactben function withLogging(WrappedComponent) { return function WithLogging(props) { console.log(`A ${WrappedComponent.name} komponens renderelése, props:`, props); return <WrappedComponent {...props} />; }; } // HOC alkalmazása const EnhancedButton = withLogging(Button); // Bővített komponens használata // <EnhancedButton label="Kattints" onClick={() => console.log('Kattintás!')} /> -
Singleton (Egyszemélyes): Biztosítja, hogy egy osztálynak csak egy példánya legyen, és globális hozzáférést biztosítson hozzá. Ezt alkalmaztam a globális állapot kezelésére vagy egyetlen szolgáltatás példányának létrehozására (pl. naplózás, konfiguráció).
// Egyszemélyes minta példája class ConfigManager { constructor() { if (ConfigManager.instance) { return ConfigManager.instance; } this.settings = {}; // Beállítások inicializálása 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 (egy és ugyanaz a példány) config1.setSetting('apiUrl', 'https://api.example.com'); console.log(config2.getSetting('apiUrl')); // https://api.example.com -
Gyármetódus (Factory Method): Meghatározza az interfészt egy objektum létrehozására, de az alosztályok döntenek arról, hogy melyik objektumot hozzák létre. Ezt alkalmaztam különböző felhasználói felület elemek vagy konfiguráció alapú objektumok létrehozására.
-
Stratégia (Strategy): Egy család algoritmusát határozza meg, mindegyiket kapszulázza, és egymással helyettesíthetővé teszi. Lehetővé teszi az algoritmus változtatását a felhasználóktól függetlenül. Ezt alkalmaztam különböző adatszortálási, űrlap-ellenőrzési vagy eseménykezelési megközelítések megvalósítására.
Ezeknek a mintáknak a használata segített strukturáltabb, modulárisabb, tesztelhetőbb és könnyebben karbantartható kód létrehozásában.