Vi siete mai chiesti quali sono i modelli di progettazione? In questo articolo, spiegherò perché i modelli di progettazione sono importanti e fornirà alcuni esempi, in PHP, di quando e perché dovrebbero essere utilizzati.
I modelli di progettazione sono ottimizzati, soluzioni riutilizzabili per i problemi di programmazione che incontriamo ogni giorno. Un modello di progettazione non è una classe o una libreria che possiamo semplicemente collegare al nostro sistema; è molto più di questo. È un modello che deve essere implementato nella situazione corretta. Non è nemmeno specifico per la lingua. Un buon modello di progettazione dovrebbe essere implementabile nella maggior parte, se non in tutte le lingue, a seconda delle capacità della lingua. Ancora più importante, qualsiasi modello di progettazione può essere un'arma a doppio taglio - se implementato nel posto sbagliato, può essere disastroso e creare molti problemi per te. Tuttavia, implementato nel posto giusto, al momento giusto, può essere il tuo salvatore.
Esistono tre tipi fondamentali di modelli di progettazione:
Strutturale i modelli generalmente trattano le relazioni tra entità, rendendo più facile per queste entità lavorare insieme.
creazionale i pattern forniscono meccanismi di istanziazione, rendendo più facile la creazione di oggetti in modo adeguato alla situazione.
comportamentale i pattern sono usati nelle comunicazioni tra entità e rendono più facile e flessibile la comunicazione tra queste entità.
Modelli di progettazione sono, per principio, soluzioni ben ponderate ai problemi di programmazione. Molti programmatori hanno già riscontrato questi problemi e hanno utilizzato queste "soluzioni" per rimediarli. Se si verificano questi problemi, perché ricreare una soluzione quando è possibile utilizzare una risposta già provata?
Immaginiamo che ti sia stata data la responsabilità di creare un modo per unire due classi che fanno due cose diverse in base alla situazione. Queste due classi sono pesantemente utilizzate dal sistema esistente in luoghi diversi, rendendo difficile rimuovere queste due classi e modificare il codice esistente. Per aggiungere a ciò, la modifica del codice esistente richiede che sia necessario testare qualsiasi codice modificato, poiché questi tipi di modifiche, in un sistema che si basa su componenti diversi, introducono quasi sempre nuovi bug. Invece di fare ciò, è possibile implementare una variante del modello di strategia e del modello dell'adattatore, che può facilmente gestire questi tipi di scenari.
_context = $ contesto; public function operation1 () if ($ this -> _ context == "context_for_class_one") $ this -> _ class_one-> operation1_in_class_one_context (); else ($ this -> _ context == "context_for_class_two") $ this -> _ class_two-> operation1_in_class_two_context ();
Abbastanza semplice, vero? Ora, diamo uno sguardo più da vicino al modello di strategia.
Il modello di strategia è un modello di progettazione comportamentale che consente di decidere quale linea di azione deve seguire un programma, in base a un contesto specifico durante il runtime. Si incapsulano due diversi algoritmi all'interno di due classi e si decide in fase di esecuzione quale strategia tu vuoi andare con.
Nel nostro esempio sopra, la strategia è basata su qualunque sia il $ contesto variabile era al momento in cui la classe è stata istanziata. Se gli dai il contesto per class_one, userà class_one e viceversa.
Immagina che stia attualmente sviluppando una classe che può aggiornare o creare un nuovo record utente. Ha ancora bisogno degli stessi input (nome, indirizzo, numero di cellulare, ecc.), Ma, a seconda di una determinata situazione, deve utilizzare diverse funzioni durante l'aggiornamento e la creazione. Ora, potresti probabilmente usare un if-else per realizzare questo, ma cosa succede se hai bisogno di usare questa classe in un posto diverso? In tal caso, dovrai riscrivere la stessa istruzione if-else di nuovo. Non sarebbe più semplice specificare il tuo contesto?
Ora, il modello di strategia "normale" implica l'incapsulamento degli algoritmi all'interno di un'altra classe, ma in questo caso, un'altra classe sarebbe dispendiosa. Ricorda che non devi seguire esattamente il modello. Le variazioni funzionano finché il concetto rimane lo stesso e risolve il problema.
Modello adattatore
Immagine per gentile concessione di http://www.uxcell.comIl modello di adattatore è un modello di progettazione strutturale che consente di riutilizzare una classe con un'interfaccia diversa, consentendone l'utilizzo da parte di un sistema che utilizza metodi di chiamata diversi.
Ciò consente anche di modificare alcuni degli input ricevuti dalla classe client, rendendoli in qualche modo compatibili con le funzioni di adaptee.
Come posso usare questo?
Un altro termine per indicare una classe dell'adattatore è a involucro, che fondamentalmente ti permette di "avvolgere" azioni in una classe e riutilizzare queste azioni nelle situazioni corrette. Un esempio classico potrebbe essere quando si sta creando una classe di dominio per le classi di tabelle. Invece di chiamare le diverse classi della tabella e richiamare le loro funzioni una per una, è possibile incapsulare tutti questi metodi in un unico metodo utilizzando una classe dell'adattatore. Ciò non solo ti consente di riutilizzare qualsiasi azione tu voglia, ma ti impedisce anche di dover riscrivere il codice se hai bisogno di usare la stessa azione in un posto diverso.
Confronta queste due implementazioni.
Approccio non adattivo
CreateOrUpdate (// input); $ profile = new Profile (); $ profile-> CreateOrUpdate (// input);Se avessimo bisogno di farlo di nuovo in un posto diverso, o addirittura di riutilizzare questo codice in un progetto diverso, dovremmo digitare tutto da capo.
Meglio
Questo è contrario a fare qualcosa del genere:
NewAccount (// input);In questa situazione, abbiamo una classe wrapper, che sarebbe la nostra classe di dominio Account:
CreateOrUpdate (// sottoinsieme di input); $ profile = new Profile (); $ profile-> CreateOrUpdate (// sottoinsieme di input);In questo modo, puoi utilizzare nuovamente il dominio del tuo account ogni volta che ne hai bisogno; inoltre, potresti raggruppare anche altre classi nella tua classe di dominio.
Modello di metodo di fabbrica
Immagine per gentile concessione di http://www.lankanewspappers.comIl metodo di fabbrica pattern è un modello di design creativo che fa esattamente come sembra: è una classe che funge da fabbrica di istanze di oggetti.
L'obiettivo principale di questo modello è incapsulare la procedura creazionale che può estendersi su classi diverse in un'unica funzione. Fornendo il contesto corretto al metodo factory, sarà in grado di restituire l'oggetto corretto.
Quando posso usare questo?
Il momento migliore per utilizzare lo schema del metodo factory è quando si hanno più varianti di una singola entità. Diciamo che hai una classe pulsante; questa classe ha diverse varianti, come ImageButton, InputButton e FlashButton. A seconda del luogo, potrebbe essere necessario creare pulsanti diversi: qui è possibile utilizzare una fabbrica per creare i pulsanti!
Iniziamo creando le nostre tre classi:
_html; classe ImageButton estende Button protected $ _html = "..."; // Questo dovrebbe essere l'HTML che vuoi per la tua classe pulsante pulsante immagine InputButton estende Button protected $ _html = "..."; // Questo dovrebbe essere l'HTML che vuoi per il tuo normale pulsante (); classe FlashButton estende Button protected $ _html = "..."; // Questo dovrebbe essere l'HTML che vuoi per il tuo pulsante basato su FlashOra possiamo creare la nostra classe di fabbrica:
Possiamo usare questo codice in questo modo:
$ buttons = array ('image', 'input', 'flash'); foreach ($ button as $ b) echo ButtonFactory :: createButton ($ b) -> getHtml ()L'output dovrebbe essere l'HTML di tutti i tipi di pulsanti. In questo modo, potresti specificare quale pulsante creare a seconda della situazione e riutilizzare anche la condizione.
Decoratore
Immagine per gentile concessione di http://www.decoratorsdarlington.co.ukIl decoratore pattern è un modello di progettazione strutturale che consente di aggiungere un comportamento nuovo o aggiuntivo a un oggetto durante il runtime, a seconda della situazione.
L'obiettivo è di fare in modo che le funzioni estese possano essere applicate a un'istanza specifica e, allo stesso tempo, essere ancora in grado di creare un'istanza originale che non ha le nuove funzioni. Consente inoltre di combinare più decoratori per un'istanza, in modo da non essere bloccati con un decoratore per ogni istanza. Questo modello è un'alternativa alla sottoclasse, che si riferisce alla creazione di una classe che eredita funzionalità da una classe genitore. A differenza della sottoclasse, che aggiunge il comportamento in fase di compilazione, "decorating" consente di aggiungere nuovi comportamenti durante il runtime, se la situazione lo richiede.
Per implementare il modello decoratore, possiamo seguire questi passaggi:
- Sottoclassi la classe "Componente" originale in una classe "Decoratore"
- Nella classe Decorator, aggiungi un puntatore Componente come campo
- Passa un componente al costruttore Decorator per inizializzare il puntatore Component
- Nella classe Decorator, reindirizza tutti i metodi "Component" al puntatore "Component" e
- Nella classe Decorator, eseguire l'override di qualsiasi metodo Component il cui comportamento deve essere modificato
Passaggi per gentile concessione di http://en.wikipedia.org/wiki/Decorator_pattern
Quando posso usare questo?
Il luogo migliore per utilizzare il modello decoratore è quando si ha un'entità che deve avere un nuovo comportamento solo se la situazione lo richiede. Supponiamo che tu abbia un elemento link HTML, un link di disconnessione, che tu voglia fare cose leggermente diverse in base alla pagina corrente. Per questo, possiamo usare il modello decoratore.
Per prima cosa, stabiliamo le diverse "decorazioni" di cui avremo bisogno.
Una volta stabilite le nostre decorazioni, possiamo iniziare a programmarle.
_html = "Esci"; public function setHtml ($ html) $ this -> _ html = $ html; public function render () echo $ this -> _ html; classe LogoutLinkH2Decorator estende HtmlLinks protected $ _logout_link; funzione pubblica __construct ($ logout_link) $ this -> _ logout_link = $ logout_link; $ This-> setHtml ("". $ questo -> _ html."
") public function __call ($ name, $ args) $ this -> _ logout_link -> $ name ($ args [0]) LogoutLinkUnderlineDecorator estende HtmlLinks protected $ _logout_link; funzione pubblica __construct ($ logout_link) $ this -> _ logout_link = $ logout_link; $ this-> setHtml ("". $ questo -> _ html."") public function __call ($ name, $ args) $ this -> _ logout_link -> $ name ($ args [0]) LogoutLinkStrongDecorator estende HtmlLinks protected $ _logout_link; funzione pubblica __construct ($ logout_link) $ this -> _ logout_link = $ logout_link; $ this-> setHtml ("". $ questo -> _ html.""); public function __call ($ name, $ args) $ this -> _ logout_link -> $ name ($ args [0])
Dovremmo quindi essere in grado di usarlo in questo modo:
$ logout_link = new LogoutLink (); if ($ is_logged_in) $ logout_link = new LogoutLinkStrongDecorator ($ logout_link); if ($ in_home_page) $ logout_link = new LogoutLinkH2Decorator ($ logout_link); else $ logout_link = new LogoutLinkUnderlineDecorator ($ logout_link); $ logout_link-> render ();
Possiamo vedere qui come siamo in grado di combinare più decoratori se ne abbiamo bisogno. Dal momento che tutti i decoratori usano il __chiamata funzione magica, possiamo ancora chiamare i metodi della funzione originale. Se supponiamo di essere attualmente nella home page e di aver effettuato l'accesso, l'output HTML dovrebbe essere:
Disconnettersi
Il singleton il modello di progettazione è un modello di progettazione creazionale che assicura di disporre di una singola istanza di una determinata classe nella durata del runtime e fornisce un punto globale di accesso alla singola istanza.
Ciò semplifica l'impostazione di un punto di "coordinamento" per altri oggetti che utilizzano anche l'istanza Singleton, poiché le variabili del singleton saranno sempre le stesse per tutto ciò che la chiama.
Se è necessario passare un'istanza specifica da una classe a un'altra, è possibile utilizzare il modello singleton per evitare di dover passare l'istanza tramite il costruttore o l'argomento. Immagina di aver creato una classe Session, che simula l'array globale $ _SESSION. Poiché questa classe dovrà essere istanziata una sola volta, possiamo implementare un modello singleton in questo modo:
Facendo ciò, possiamo accedere alla nostra istanza di sessione da diverse parti del nostro codice, anche in classi diverse. Questi dati verranno mantenuti durante tutte le chiamate getInstance.
Conclusione
Ci sono molti altri modelli di design da studiare; in questo articolo, ho solo evidenziato alcuni dei più importanti che uso durante la programmazione. Se sei interessato a leggere gli altri modelli di design, la pagina dei modelli di design di Wikipedia ha una miriade di informazioni. Se ciò non bastasse, puoi sempre controllare Patterns di progettazione: elementi del software orientato agli oggetti riutilizzabile, che è considerato uno dei migliori libri di design disponibili.
Un'ultima cosa: quando usi questi schemi di progettazione, alwAYS assicurati di provare a risolvere il problema corretto. Come ho detto prima, questi modelli di design sono una spada a doppio taglio: se usati nel contesto sbagliato, possono potenzialmente peggiorare le cose; ma se usati correttamente, diventano indispensabili.
Se hai trovato utile questo tutorial, perché non controllare l'intervallo di script PHP su Envato Market. Esistono migliaia di script utili che possono accelerare lo sviluppo e aiutarti a ottenere risultati migliori. Puoi trovare sistemi di prenotazione, moduli di contatto AJAX, sistemi di newsletter e molto altro.
Script PHP su Envato Market