I modelli di progettazione sono soluzioni a livello di progettazione per problemi ricorrenti che noi ingegneri del software incontriamo spesso. Non è codice – ripeto, CODE CODICE. È come una descrizione su come affrontare questi problemi e progettare una soluzione.

L’utilizzo di questi modelli è considerato una buona pratica, poiché il design della soluzione è abbastanza collaudato e testato, con conseguente maggiore leggibilità del codice finale., I modelli di progettazione sono spesso creati e utilizzati dai linguaggi OOP, come Java, in cui la maggior parte degli esempi da qui in poi verrà scritta.

Tipi di modelli di progettazione

Ci sono circa 26 Modelli attualmente scoperti (difficilmente penso che li farò tutti…).

Questi 26 possono essere classificati in 3 tipi:

1. Creational: questi modelli sono progettati per l’istanziazione di classe. Possono essere modelli di creazione di classi o modelli di creazione di oggetti.

2. Strutturale: Questi modelli sono progettati per quanto riguarda la struttura e la composizione di una classe., L’obiettivo principale della maggior parte di questi modelli è quello di aumentare la funzionalità delle classi coinvolte, senza modificare gran parte della sua composizione.

3. Comportamentale: questi modelli sono progettati a seconda di come una classe comunica con gli altri.

In questo post, passeremo attraverso un modello di progettazione di base per ogni tipo classificato.

Tipo 1: Creational – Il modello di progettazione Singleton

Il modello di progettazione Singleton è un modello creazionale, il cui obiettivo è quello di creare una sola istanza di una classe e di fornire un solo punto di accesso globale a tale oggetto., Un esempio comunemente usato di tale classe in Java è Calendar, in cui non è possibile creare un’istanza di quella classe. Utilizza anche il proprio metodogetInstance() per ottenere l’oggetto da utilizzare.

Una classe che utilizza il modello di progettazione singleton includerà,

Diagramma di classe Singleton
  1. Una variabile statica privata, contenente l’unica istanza della classe.
  2. Un costruttore privato, quindi non può essere istanziato da nessun’altra parte.
  3. Un metodo statico pubblico, per restituire la singola istanza della classe.,

Esistono molte diverse implementazioni del design singleton. Oggi, passerò attraverso le implementazioni di;

1. Istanziazione desiderosa

2. Istanziazione pigra

3. Istanziazione thread-safe

Eager Beaver

public class EagerSingleton {// create an instance of the class.private static EagerSingleton instance = new EagerSingleton();// private constructor, so it cannot be instantiated outside this class.private EagerSingleton() { }// get the only instance of the object created.public static EagerSingleton getInstance() {return instance;}}

Questo tipo di istanziazione avviene durante il caricamento della classe, poiché l’istanziazione dell’istanza variabile avviene al di fuori di qualsiasi metodo. Ciò pone un grave inconveniente se questa classe non viene utilizzata affatto dall’applicazione client. Il piano di emergenza, se questa classe non viene utilizzata, è l’istanza Lazy.,

Lazy Days

Non c’è molta differenza rispetto all’implementazione di cui sopra. Le principali differenze sono che la variabile statica viene inizialmente dichiarata null e viene istanziata solo all’interno del metodo getInstance() se – e solo se – la variabile di istanza rimane null al momento del controllo.

Questo risolve un problema, ma ne esiste ancora un altro. Cosa succede se due client diversi accedono alla classe Singleton contemporaneamente, direttamente al millisecondo?, Bene, controlleranno se l’istanza è null allo stesso tempo, e la troveranno vera, e così creeranno due istanze della classe per ogni richiesta da parte dei due client. Per risolvere questo problema, l’istanziazione Thread Safe deve essere implementata.

(Thread) La sicurezza è la chiave

In Java, la parola chiave synchronized viene utilizzata su metodi o oggetti per implementare la sicurezza dei thread, in modo che solo un thread possa accedere a una particolare risorsa contemporaneamente. L’istanziazione della classe viene inserita in un blocco sincronizzato in modo che il metodo possa essere accessibile solo da un client alla volta.,

Il sovraccarico per il metodo sincronizzato è elevato e riduce le prestazioni dell’intera operazione.

Ad esempio, se la variabile di istanza è già stata istanziata, ogni volta che un client accede al metodogetInstance(), viene eseguito il metodosynchronized e le prestazioni diminuiscono. Questo accade solo per verificare se il valore delle variabili instance è null. Se scopre che lo è, lascia il metodo.

Per ridurre questo sovraccarico, viene utilizzato il doppio blocco., Il controllo viene utilizzato anche prima del metodosynchronized e, se il valore è null da solo, viene eseguito il metodosynchronized.

Ora sulla prossima classificazione.

Tipo 2: Structural – The Decorator Design Pattern

Ti darò un piccolo scenario per dare un contesto migliore al perché e dove dovresti usare il Pattern Decorator.

Dire che si possiede un negozio di caffè, e come ogni principiante, si inizia con solo due tipi di caffè normale, la miscela di casa e arrosto scuro., Nel tuo sistema di fatturazione, c’era una classe per le diverse miscele di caffè, che eredita la classe astratta delle bevande. Le persone in realtà iniziano a venire e hanno il tuo meraviglioso (anche se amaro?) caff. Poi ci sono i newbs caffè che, Dio non voglia, vogliono zucchero o latte. Che parodia per il caffè!! ??

Ora è necessario disporre di questi due componenti aggiuntivi, sia per il menu e, purtroppo, sul sistema di fatturazione. Originariamente, la tua persona IT farà una sottoclasse per entrambi i caffè, uno compreso lo zucchero, l’altro latte., Poi, dato che i clienti hanno sempre ragione, si dicono queste parole temute:

“Posso avere un caffè al latte, con lo zucchero, per favore?”

???

Ci va il sistema di fatturazione ridere in faccia di nuovo. Bene, torniamo al tavolo da disegno….

La persona IT aggiunge quindi milk coffee con sugar come un’altra sottoclasse a ciascuna classe di caffè genitore. Il resto del mese è una navigazione tranquilla, la gente in fila per avere il caffè, in realtà fare soldi. ??

Ma aspetta, c’è di più!

Il mondo è di nuovo contro di te., Un concorrente si apre dall’altra parte della strada, con non solo 4 tipi di caffè, ma più di 10 add-ons pure! ?

Si acquista tutti quelli e di più, per vendere meglio il caffè da soli, e solo allora ricordare che si è dimenticato di aggiornare quel sistema di fatturazione dratted. È molto probabilmente non può fare il numero infinito di sottoclassi per qualsiasi e tutte le combinazioni di tutti i componenti aggiuntivi, con le nuove miscele di caffè troppo. Per non parlare della dimensione del sistema finale.??

Tempo di investire effettivamente in un sistema di fatturazione adeguato., Trovi nuovo personale IT, che in realtà sa cosa stanno facendo e dicono;

“Perché, questo sarà molto più facile e più piccolo se ha usato il pattern decorator.”

Che diavolo è?

Il modello di progettazione decoratore rientra nella categoria strutturale, che si occupa della struttura effettiva di una classe, sia per ereditarietà, composizione o entrambi. L’obiettivo di questo progetto è modificare la funzionalità di un oggetto in fase di esecuzione. Questo è uno dei molti altri modelli di progettazione che utilizzano classi astratte e interfacce con la composizione per ottenere il risultato desiderato.,

Diamo una possibilità alla matematica (rabbrividire?) per portare tutto questo in prospettiva;

Prendere 4 miscele di caffè e 10 componenti aggiuntivi. Se abbiamo attaccato alla generazione di sottoclassi per ogni diversa combinazione di tutti i componenti aggiuntivi per un tipo di caffè. Questo è;

(10-1)2 = 92 = 81 sottoclassi

Sottraiamo 1 dal 10, poiché non è possibile combinare un componente aggiuntivo con un altro dello stesso tipo, lo zucchero con lo zucchero sembra stupido. E questo è per una sola miscela di caffè. Moltiplicare che 81 per 4 e si ottiene un enorme 324 diverse sottoclassi!, Parlare di tutto ciò che codifica

Ma con il modello decoratore richiederà solo 16 classi in questo scenario. Vuoi scommettere?

Design Pattern Decorator diagramma di Classe
diagramma di Classe secondo negozio di caffè scenario

Se si mappa il nostro scenario secondo il diagramma delle classi di cui sopra, abbiamo 4 classi per il 4 miscele di caffè, 10 per ogni add-on e 1 per l’astratto componente e 1 per l’astratto decoratore. Vedi! 16!, Ora consegnami quei 100 dollari.?? (jk, ma non verrà rifiutato se dato saying solo dicendo)

Come puoi vedere dall’alto, proprio come le miscele di caffè concrete sono sottoclassi della classe astratta delle bevande, anche la classe astratta AddOn eredita i suoi metodi da esso. I componenti aggiuntivi, che sono le sue sottoclassi, a loro volta ereditano nuovi metodi per aggiungere funzionalità all’oggetto di base quando necessario.

Passiamo alla codifica, per vedere questo modello in uso.,

Prima di creare la classe di bevande astratte, che tutte le diverse miscele di caffè erediteranno da:

Quindi aggiungere entrambe le classi di miscela di caffè concrete.

La classe astratta AddOn eredita anche dalla classe astratta Beverage (più su questo sotto).

E ora le implementazioni concrete di questa classe astratta:

Come puoi vedere sopra, possiamo passare qualsiasi sottoclasse di Beverage a qualsiasi sottoclasse di AddOn e ottenere il costo aggiunto e la descrizione aggiornata. E, poiché la classe AddOn è essenzialmente di tipo Beverage, possiamo passare un AddOn in un altro AddOn., In questo modo, possiamo aggiungere qualsiasi numero di componenti aggiuntivi a una specifica miscela di caffè.

Ora scrivere del codice per testarlo.

Il risultato finale è:

P.S. questo è in Rupie dello Sri Lanka

Funziona! Siamo stati in grado di aggiungere più di un add-on per una miscela di caffè e aggiornare con successo il suo costo finale e la descrizione, senza la necessità di fare sottoclassi infinite per ogni combinazione add-on per tutte le miscele di caffè.

Infine, all’ultima categoria.,

Tipo 3: Comportamentale – Il modello di progettazione dei comandi

Un modello di progettazione comportamentale si concentra su come classi e oggetti comunicano tra loro. L’obiettivo principale del modello di comando è quello di inculcare un più alto grado di accoppiamento libero tra le parti coinvolte (leggi: classi).

Uhhhh What Che cos’è?

L’accoppiamento è il modo in cui due (o più) classi che interagiscono tra loro, beh, interagiscono. Lo scenario ideale quando queste classi interagiscono è che non dipendono pesantemente l’una dall’altra. E ‘ un accoppiamento libero., Quindi, una definizione migliore per l’accoppiamento libero sarebbe, classi che sono interconnesse, facendo il minimo uso l’una dell’altra.

La necessità di questo modello è nata quando le richieste dovevano essere inviate senza sapere consapevolmente cosa si sta chiedendo o chi è il destinatario.

In questo modello, la classe di richiamo viene disaccoppiata dalla classe che esegue effettivamente un’azione. La classe invoker ha solo il metodo callable execute, che esegue il comando necessario, quando il client lo richiede.

Prendiamo un esempio di base del mondo reale, ordinando un pasto in un ristorante di lusso., Mentre il flusso va, dai il tuo ordine (comando) al cameriere (invoker), che poi lo consegna allo chef(ricevitore), in modo da poter ottenere cibo. Potrebbe sembrare semplice but ma un po ‘ meh al codice.

L’idea è piuttosto semplice, ma la codifica va intorno al naso.,

Command Design Pattern Class Diagram

Il flusso di funzionamento sul lato tecnico è, si effettua un comando concreto, che implementa l’interfaccia di comando, chiedendo al ricevitore di completare un’azione, e inviare il comando al invocatore. L’invoker è la persona che sa quando dare questo comando. Lo chef è l’unico che sa cosa fare quando viene dato il comando/ordine specifico., Pertanto, quando viene eseguito il metodo execute dell’invoker, a sua volta, il metodo execute degli oggetti command viene eseguito sul ricevitore, completando così le azioni necessarie.,

Quello di cui abbiamo bisogno per implementare;

  1. Un’interfaccia di Comando
  2. Un Ordine di classe che implementa l’interfaccia di Comando
  3. Una classe Cameriere (invoker)
  4. Un Chef di classe (ricevitore)

Così, la codifica va come questa:

Chef, il ricevitore

Comando, l’interfaccia

public interface Command {public abstract void execute();}

Ordine, il calcestruzzo di comando

Cameriere, l’invoker

public class Waiter {private Order order;public Waiter(Order ord) {this.order = ord;}public void execute() {this.order.execute();}}

Si, il client

Come si può vedere sopra, il Cliente effettua un Ordine e imposta il Ricevitore come Chef., L’Ordine viene inviato al cameriere, che saprà quando eseguire l’Ordine (cioè quando dare allo chef l’ordine di cucinare). Quando viene eseguito l’invoker, il metodo di esecuzione degli ordini viene eseguito sul ricevitore (cioè allo chef viene dato il comando di cucinare la pasta ? o cuocere la torta?).,

Cliente Finale di Uscita

un breve riassunto

In questo post siamo andati attraverso:

  1. Cosa un design pattern è davvero,
  2. I diversi tipi di modelli di progettazione e perché sono diverso
  3. Una base o comuni design pattern per ogni tipo di

spero di essere stato utile.

Trova il repository del codice per il post, qui.