Separare un'astrazione dalla sua implementazione in modo che entrambe possano variare indipendentemente.
Quando un'astrazione può avere diverse implementazioni.
Per evitare che l'ereditarietà leghi permanentemente un'implementazione all'astrazione.
Esempio: Un toolkit per interfacce utente deve supportare sia il Sistema X Windows che il Presentation Manager (PM) IBM. La composizione è più flessibile dell'ereditarietà per gestire questa esigenza.
Per evitare un legame permanente tra astrazione e implementazione.
Per selezionare o cambiare implementazioni a runtime.
Per estendere indipendentemente astrazioni e implementazioni.
Per nascondere l'implementazione di un'astrazione ai client.
Per evitare la proliferazione di classi derivata da combinazioni di astrazioni e implementazioni.
Abstraction (Window): Definisce l'interfaccia dell'astrazione e mantiene un riferimento a un Implementor.
RefinedAbstraction (IconWindow): Estende l'interfaccia definita da Abstraction.
Implementor (WindowImp): Definisce l'interfaccia per le classi di implementazione, che può differire da quella di Abstraction.
ConcreteImplementor (XWindowImp, PMWindowImp): Implementa l'interfaccia di Implementor.
Abstraction inoltra le richieste dei client al suo oggetto Implementor.
Implementor esegue l'azione richiesta.
Separazione tra interfaccia e implementazione:
L'implementazione non è più legata permanentemente a un'interfaccia.
Può essere configurata o cambiata a runtime.
Elimina le dipendenze di compilazione sull'implementazione.
Estensibilità migliorata:
Aggiunta indipendente di nuove astrazioni e implementazioni.
Nascondere i dettagli ai client:
Protegge i client dai dettagli dell'implementazione, come condivisione degli oggetti implementatori e conteggio dei riferimenti.
Un solo Implementor: Anche con una singola implementazione, separare astrazione e implementazione evita ricompilazioni in caso di cambiamenti.
Creazione dell'oggetto Implementor:
Istanziare direttamente nel costruttore.
Usare un'implementazione predefinita e cambiarla in seguito.
Delegare la creazione a un altro oggetto, come Abstract Factory o Singleton.
Condivisione degli implementatori: Utilizzare lo stesso Implementor per più astrazioni.
Ereditarietà multipla in C++: Combinare interfaccia e implementazione, ma lega permanentemente i due.
in molte applicazioni
Abstract Factory: Per creare oggetti Implementor appropriati.
Adapter: Per adattare un'implementazione esistente a una nuova interfaccia.