Introduzione ai Design Pattern
Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 90 di 104.
I design pattern sono soluzioni collaudate e riutilizzabili a problemi comuni che si presentano nella progettazione del software. Non sono codice da copiare direttamente: sono modelli o schemi che descrivono come strutturare classi e oggetti per risolvere con eleganza sfide specifiche.
Il concetto è stato reso popolare dalla "Gang of Four" (GoF) nel loro libro del 1994, che catalogava 23 modelli fondamentali. Questi modelli sono generalmente raggruppati in tre categorie:
| Categoria | Scopo | Esempi |
|---|---|---|
| Creazionali | Meccanismi di creazione degli oggetti | Singleton, Factory, Builder |
| Strutturali | Composizione di classi e oggetti | Adapter, Decorator, Composite |
| Comportamentali | Interazione e responsabilità degli oggetti | Observer, Strategy, Command |
Perché imparare i pattern di progettazione? Forniscono un vocabolario condiviso tra gli sviluppatori: dire «usa una Factory qui» comunica all’istante un’idea complessa. Ti aiutano anche a evitare di reinventare soluzioni e rendono il tuo codice più flessibile e manutenibile.
In C++, i pattern di progettazione sfruttano le funzionalità OOP che hai già imparato: ereditarietà, polimorfismo, classi astratte e template. Nelle prossime lezioni, implementerai diversi pattern essenziali e capirai quando ciascuno è lo strumento giusto per il compito.
Sfida
FacileCostruiamo un semplice classificatore di pattern che dimostri la tua comprensione delle tre categorie di pattern di progettazione. Creerai un sistema che riceve il nome di un pattern e identifica a quale categoria appartiene, Creational, Structural o Behavioral, insieme a una breve descrizione dello scopo di quella categoria.
Organizzerai il codice in tre file:
PatternCategory.h: Definisci una classe base astratta chiamataPatternCategoryche rappresenta una categoria di pattern di progettazione. Dovrebbe avere:- Un metodo virtuale puro
getName()che restituisce il nome della categoria come stringa - Un metodo virtuale puro
getPurpose()che restituisce una descrizione di ciò che fanno i pattern di questa categoria - Un distruttore virtuale
Quindi crea tre classi derivate che ereditano da
PatternCategory:CreationalCategory: restituisce il nome"Creational"e lo scopo"Object creation mechanisms"StructuralCategory: restituisce il nome"Structural"e lo scopo"Class and object composition"BehavioralCategory: restituisce il nome"Behavioral"e lo scopo"Object interaction and responsibility"
- Un metodo virtuale puro
PatternClassifier.h: Crea una classePatternClassifierin grado di identificare a quale categoria appartiene un dato pattern.Il classificatore dovrebbe avere un metodo
classifyche accetta il nome di un pattern (stringa) e restituisce un puntatore allaPatternCategoryappropriata. Usa puntatori intelligenti (std::unique_ptr) per la gestione della memoria.Il classificatore dovrebbe riconoscere questi pattern:
- Creational:
Singleton,Factory,Builder - Structural:
Adapter,Decorator,Composite - Behavioral:
Observer,Strategy,Command
Se il nome del pattern non viene riconosciuto, restituisci
nullptr.- Creational:
main.cpp: Leggi un singolo input: il nome di un pattern di progettazione.Crea un
PatternClassifiere usalo per classificare il pattern inserito. Se il pattern viene riconosciuto, stampa:[PatternName] is a [CategoryName] pattern Purpose: [CategoryPurpose]Se il pattern non viene riconosciuto, stampa:
Unknown pattern: [PatternName]
Ad esempio, con l'input Singleton:
Singleton is a Creational pattern
Purpose: Object creation mechanismsCon l'input Observer:
Observer is a Behavioral pattern
Purpose: Object interaction and responsibilityCon l'input Proxy:
Unknown pattern: ProxyQuesta sfida rafforza la conoscenza delle tre categorie di pattern di progettazione e ti permette di esercitarti con ereditarietà, polimorfismo e puntatori intelligenti: concetti che hai già padroneggiato. La struttura in più file rispecchia il modo in cui i progetti reali organizzano classi correlate.
Provalo tu
#include <iostream>
#include <string>
#include "PatternClassifier.h"
int main() {
// Leggi il nome del pattern
std::string patternName;
std::cin >> patternName;
// TODO: Crea un'istanza di PatternClassifier
// TODO: Usa il classificatore per classificare il pattern di input
// TODO: Se il pattern viene riconosciuto, stampa:
// "[PatternName] is a [CategoryName] pattern"
// "Purpose: [CategoryPurpose]"
// TODO: Se il pattern non viene riconosciuto (nullptr), stampa:
// "Unknown pattern: [PatternName]"
return 0;
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniBuild e compilazione in C++File header e file sorgenteNamespace e ambitoIntroduzione alla programmazione orientata agli oggetti in C++Classi e oggetti a confrontoIl puntatore 'this'Metodi (funzioni membro)Attributi (membri dati)Fondamenti di costruttori e distruttoriRiepilogo - Calcolatrice semplice4Proprietà delle classi
Membri di istanza e staticiGetter e setterFunzioni membro constParola chiave mutableMetodi e variabili staticiFunzioni e classi friendRiepilogo - Gestore di conti bancari7Ereditarietà
Ereditarietà di baseLivelli di accesso nell’ereditarietàOrdine di chiamata di costruttori e distruttoriRidefinizione dei metodiFunzioni virtuali e VTableEreditarietà multiplaEreditarietà virtualeRiepilogo - Gerarchia dei dipendenti10Panoramica della STL
Panoramica e filosofia della STLContenitori STLIteratoriAlgoritmi STLFuntori ed espressioni lambdaRiepilogo - Frequenza delle parole13Design Pattern Parte 1
Introduzione ai Design PatternPattern SingletonFactory e Abstract FactoryPattern BuilderPattern ObserverPattern Strategy2Gestione della memoria
Memoria Stack vs HeapPuntatori e riferimentiMemoria dinamica (new/delete)Puntatori intelligenti in C++RAII in C++Riepilogo - Gestore di array dinamico5Incapsulamento
Specificatori di accesso in C++Specificatori di accesso in dettaglioOccultamento delle informazioniStruct vs classClassi annidate e interneRiepilogo - Sistema di registrazione degli studenti8Polimorfismo
Polimorfismo a compile time e a runtimeOverload delle funzioniFunzioni virtuali: ripassoFunzioni virtuali pureClassi astratteProgettazione delle interfacce in C++Dynamic casting e RTTIRipasso: calcolatrice di forme11Concetti avanzati di OOP
Composizione vs ereditarietàMixin tramite CRTPIdiom PimplType ErasureEnum class e tipizzazione forteGestione delle eccezioni in OOPGerarchie personalizzate di eccezioni14Pattern di progettazione - Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeRAII come pattern3Costruttori e distruttori
Costruttore predefinitoCostruttore con parametriCostruttore di copiaCostruttore di spostamentoListe di inizializzazione dei costruttoriCostruttori delegantiApprofondimento sui distruttoriRegola del Tre / Cinque / ZeroRipasso - classe String6Sovraccarico degli operatori
Introduzione al sovraccarico degli operatoriSovraccarico degli operatori aritmeticiSovraccarico degli operatori di confrontoOperatori di flussoSovraccarico dell'operatore di assegnazioneSovraccarico degli operatori [] e ()Operatori di conversione di tipoRipasso - Classe Matrix9Template
Template di funzioneTemplate di classeSpecializzazione dei templateTemplate variadiciBasi di SFINAE e dei trait di tipoRiepilogo - Contenitore genericoEsercitati da solo: Compilatore C++ online