Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

oop e design pattern

No description
by

lorenzo iannone

on 11 October 2013

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of oop e design pattern

Design Pattern
OOP
&
Design Pattern
Come si programmava prima dell'oop?
Programmazione non strutturata (tanti anni fa...)
i software erano un unico grande elenco di istruzioni, non esisteva il concetto di routine
Programmazione procedurale

La prima grande rivoluzione, nascono le routine: il codice diventa strutturato
Programmazione non strutturata...
Che ne parliamo a fare?
provate a scrivere immobilare.it in un unico file php senza usare function(..)
Programmazione
Procedurale
OOP
Programmazione
non strutturata ...
Programmazione
Procedurale
un solo blocco di codice interagisce con tutti i dati
tanti blocchi di codice consumano i dati
Con l'oop non si definiscono più azioni, ma concetti
il codice incapsula i dati.
definito un concetto può essere riusato in modo agevole
il codice si decompone in blocchi più piccoli
diventa più facile da manutenere
più persone possono occuparsi di singoli blocchi
una volta scritta e testata la procedura, restituirà sempre risultati corretti
nasce il concetto di riuso
OOP
Design Pattern
L'introduzione degli oggetti rende comune l'uso di "soluzioni progettuali generali a problemi ricorrenti"
Nel 1995 la
gang of four
individua 23 pattern
Design Patterns: Elementi per il riuso di software ad oggetti di Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides
Strutturali
I pattern strutturali suggeriscono di riutilizzare oggetti già esistenti fornendo agli utilizzatori un'interfaccia più adatta alle loro esigenze.
Creazionali
Nascondono i costruttori di classi dietro interfacce.Non si deve conoscere l'implementazione per usare l'oggetto
Comportamentali
Forniscono modelli per i più comuni tipi di interazione tra gli oggetti
In seguito sono stati definiti altri tipi di Pattern.
Concorrenza
: gestiscono l'interazione tra task
Architetturali

: definiscono modelli noti di architettura per la progettazione di sistemi
Esempi famosi:
MVC, SOA
Strutturali
Facade
Serve a semplificare l'interfaccia di una o più classi
esponendo meno metodi meno complessi
class
Hotel {
...

public function
riservaStanza(
$nomeCliente
,
$città
,
$dataInizio
,
$dataFine
) { ... }
}

class
Aereo {
...

public function
prenotaPosto(
$partenza
,
$destinazione
,
$nomeCliente
,
$dataAndata
,
$dataRitorno
) {...}
}

class
AutoNoleggio {
...

public function
noleggia (
$nomeCliente
,
$dataRitiro
,
$dataConsegna
) {...}
}

class
FacadeViaggio {

public function
prenotaViaggio (
$nomeCliente
,
$partenza
,
$destinazione
,
$dataInizio
,
$dataFine
) {

$aereo
=
new
Aereo();

$hotel
=
new
Hotel();

$auto
=
new
AutoNoleggio();

$aereo
->prenotaPosto(
$partenza
,
$destinazionie
,
$nomeCliente
,
$dataInizio
,
$dataFine
);

$hotel
->riservaStanza(
$nomeCliente
,
$destinazione
,
$dataInizio
,
$dataFine
);

$auto
->noleggia(
$nomeCliente
,
$dataInizio
,
$dataFine
);
}
}

Facade
Facade
Pro:
semplifica il numero e la complessità delle classi che il client deve invocare.
Il client è indipendente dalle interfacce delle classi originali: possono essere cambiate senza cambiare il client
Contro:
La classe facade è meno potente delle classi originali: si perdono funzionalità
Decorator
Serve ad aggiungere fuzionalità ad una classe durante il
run-time
interface
InterfaceProgrammatore {

public function
progettaCodice(
$problema
);

public function
scriviCodice(
$linguaggio
);
}

class
Programmatore
implements
InterfaceProgrammatore {

public function
progettaCodice(
$problema
) {..}

public function
scriviCodice(
$linguaggio
){..}
}

abstract class
DecoratorProgrammatore
implements
InterfaceProgrammatore {

protected

$programmatore
;

public function
__construct(InterfaceProgrammatore
$prog
){

$this
-
>
programmatore
=
$prog
;
}

abstract
public function
progettaCodice(
$problema
);

abstract
public function
scriviCodice(
$linguaggio
);
}



class
ProgrammatoreImmobiliareIt
extends
DecoratorProgrammatore {

public function
progettaCodice(
$problema
) {

$this
->prendiCaffe(
new
Macchinetta());

$this
->
programmatore
->progettaCodice();
}

public function
scriviCodice(
$linguaggio
){

$this
->
programmatore
->scriviCodice($linguaggio);

$this
->testaCodice();
}

protected function
prendiCaffe(
$macchinetta
) {...}

protected function
testaCodice() {...}
}

class
ResponsabileImmobiliareIt
extends
DecoratorProgrammatore {

public function
progettaCodice(
$problema
) {

$this
->fumaSigaretta();

$this
->
programmatore
->progettaCodice();
}

public function
scriviCodice(
$linguaggio
){

$this
->
programmatore
->scriviCodice($linguaggio);

$this
->rilasciaCodice();
}

protected function
fumaSigaretta() {...}

protected function
rilasciaCodice() {...}
}


Decorator
Decorator
Decorator
Pro:
estende il comportamento di una classe al runtime
creando nuovi decoratori che accettano altri decoratori come parametri del costruttore si può simulare l'ereditarietà multipla
si può aggiungere funzionalità alle classi final
Contro:
'decorando' troppo si si creano tanti piccoli oggetti: manutenzione difficile
Proxy
Il proxy fa da mediatore tra una classe client e una classe target: interponendosi tra le due consente di eseguire i metodi della classe target solo quando è davvero necessario


interface
InterfacePlanimetria {

public

function
mostraPlanimetria();
}

class
Planimetria
implements
InterfacePlanimetria {

private

$path
;


public function
__construct(
$path
) {

$this-
>
path
=
$path
;

$this
->caricaDaDisco();
}


public function
caricaDaDisco() {
//la planimetria è grossa e ci vuole un sacco di tempo
}

public function
mostraPlanimetria { ... }
}


Proxy
Proxy
Pro
consente di differire l'esecuzione di metodi fino al momento del reale bisogno: risparmio di risorse
Creazionali
Singleton
Serve a garantire che una classe possa essere istanziata una sola volta.
Singleton
class
Singleton {


private static

$instance
=
null
;


private function
__construct() { ... }


public static function
getInstance() {

if
(
self
::
$instance
==
null
) {

self
::
$instance
=
new
Singleton();
}

return self
::
$instance
;
}


public function
doSomething() {
.....
}
}


Client:


$x
= Singleton::getInstance();

$x
->doSomething();

Singleton
Pro:
Esiste una sola istanza: minor consumo di risorse rispetto ad N oggetti identici.
Spesso evita l'uso di variabili globali
Contro:
Usa metodi statici: in molti linguaggi i singleton non sono serializzabili
Come per le variabili globali non offre nessun controllo sullo scope: il codice può accedere al singleton come e quando vuole.
Factory
Serve a creare un oggetto al runtime, specificandone la classe solo nel momento dell'effettiva esecuzione.
Factory
class
Factory{

public static function
build(
$type
)
{

if
(
!class_exists
(
$type
)) {
//controlla che la classe implementi interfacciaVeicolo

throw new
Exception(
'Class not found'
);
}

return new

$type
();
}
}

class
Automobile
implements
InterfacciaVeicolo{ ... }

class
Motocicletta
implements
InterfacciaVeicolo { ... }


Client:

try
{

$macchina
= Factory::build('
Automobile'
);

$moto
= Factory::build(
'Motocicletta'
);
$macchina
->viaggia();
$moto
->viaggia();
} catch (Exception
$e
) {
echo
$e
->getMessage();
}

Factory
Pro:
Centralizza la creazione degli oggetti
Demanda la scelta della classe al runtime
In caso di logiche di creazione complesse le nasconde all'utilizzatore
In php è di facile implementazione
Contro:
L'aggiunta di nuove classi comporta sempre la modifica del metodo factory
Comportamentali
Builder
Il Builder astrae la costruzione di un oggetto: risolve l'esigenza di avere tanti costruttori che istanziano oggetti differenti .
Piuttosto che invocare direttamente il costruttore si richiede l'istanza ad un oggetto detto Director che sa come assemblare l'oggetto voluto.

Esempio:
Classe Pizza, istanze note Margherita, Al Prosciutto.
Costruttore: pizzaiolo


/** Director */
class
Pizzaiolo {

public function
setPizzaBuilder(PizzaBuilder
$pb
) {

$this
->
pizzaBuilder
=
$pb
;
}

public function
Pizza getPizza() {

return

$this
->
pizzaBuilder
r->getPizza();
}


public function
constructPizza(){

$this
->
pizzaBuilder
->createNewPizza();

$this
->
pizzaBuilder
->buildSalsa();

$this
->
pizzaBuilder
->buildCondimento();
}
}

Client:
$pizzaiolo
=
new
Pizzaiolo();
$margheritaBuilder
=
new
PizzaMargheritaBuilder();
$prosciuttoBuilder
=
new
PizzaProsciuttoBuilder();

$pizzaiolo
->setPizzaBuilder(
$margheritaBuilder
);
$pizzaiolo
->constructPizza();

$pizza
=
$pizzaiolo
->getPizza();


class
Pizza {

private

$salsa
=
""
;

private

$condimento
=
""
;


public function
setSalsa($salsa) {
$this
->
salsa
=
$salsa
;}

public function
setCondimento(
$condimento
) {
$this
->
condimento
=
$condimento
;}
}


abstract class
PizzaBuilder
{

private

$pizza
;


public function
getPizza() {

return

$this
->
pizza
;
}

public createNewPizza(){

$this
->
pizza
= new Pizza();
}


public abstract function
buildSalsa();

public abstract function
buildCondimento();
}


class
PizzaMargheritaBuilder
extends
PizzaBuilder {

public function
buildSalsa() {

$this
->
pizza
->setSalsa(
"pomodoro"
);
}

public function
buildCondimento() {

$this
->
pizza
->setCondimento(
"mozzarella"
);
}
}

class
PizzaProsciuttoBuilder
extends
PizzaBuilder {

public function
buildSalsa() {

$this
->
pizza
->setSalsa(
"pomodoro"
);
}

public function
buildCondimento() {

$this
->
pizza
->setCondimento(
"mozzarella prosciutto"
);
}
}

Builder
Builder
Builder
Pro:
Costruttori più semplici: la logica di controllo è nei builder, evitiamo una lista di parametri infinita.
L'oggetto è valido già al momento della creazione
Contro:
È tipicamente necessario un builder per ogni prodotto: più classi da scrivere
Tra una invocazione e l'altra del Director non vengono ripuliti gli stati del Builder.
Contro:
il client non ha il controllo su quando vengono impegnate le risorse
la cache potrebbe non essere allineata con il servizio
Singleton
Configurazione di un'applicazione: ad esempio i file sys_server e sys_application di immobiliare.it potrebbero diventare un singleton.

Hanno origini nel campo dell’architettura, da parte di Christopher Alexander che notò che nella costruzione di edifici ci sono problemi progettuali ricorrenti.

Descrisse quindi le migliori
soluzioni note nel libro
“A Pattern Language” (1977).

Design Pattern
Design Pattern
Nel campo dell'informatica viene ripresa questa metodologia
Design Pattern
Originariamente vengono suddivisi
in tre categorie:
strutturali
creazionali
comportamentali
Observer
Quando un oggetto cambia stato tutti gli altri oggetti che sono interessati a tale cambiamento ne vengono informati e agiscono di conseguenza.
Observer
interface
ObserverInterface() {

public function
update(ObserverInterface
$s
);
}

interface
ObservedInterface {

public function
registerObserver(ObserverInterface
$o
);

public function
notify(Observer
$o
):
}

class
Giornale
implements
ObservedInterface {

private

$listaObserver
;

private

$notizia
;


public function
__construct() {

$this
->
listaObserver
=
array
();
}


public function
registerObserver($ObserverInterface
$o
) {

$this
->
listaObserve
r[] =
$o
;
}


public function
setNotizia (
$notizia
) {

$this
->
notizia
=
$notizia
;
}


public function
getNotizia() {

return

$this
->
notizia
;
}



public function
notify() {

foreach
(
$this
-
>listaObserver
as
$observer
) {

$observer
->update();
}
}
}


class
Lettore
implements
ObserverInterface {

public function
update($SubjectInterface
$giornale
) {

echo
"Leggo la notizia "
.
$giornale-
>getNotizia();
}
}

class
Inviato
implements
ObserverInterface {

public function
update($SubjectInterface
$giornale
) {

$notizia
= $giornale->getNotizia();
if(
$notizia
==
"ATTENTATO"
){

$this
->trasformatiInSuperman():
}
}

public function
trasformatiInSuperman() {
//leva gli occhiali
//mettiti le mutande sul pantalone
//pettinati come un cretino
}
}
client:

$giornale
= new Giornale();

$mario
= new Lettore();
$raffaele
= new Lettore();
$clarkKent
= new Inviato();

$giornale
->registerObserver(
$mario
);
$giornale
->registerObserver(
$raffale
);
$giornale
->registerObserver(
$clarkKent
);

$giornale
->setNotizia(
"ATTENTATO!"
);
$giornale
->notify();

// $mario e $raffaele leggono la notizia
// $clarkKent agisce!!

Observer
Observer
Pro:
tutte le notifiche di cambiamento avvengono con una sola chiamata
L'observed non deve conoscere nulla degli observer tranne il metodo update.
Contro:
Può essere scomodo passare i parametri agli observer in modo sufficientemente generico.
Cicli infiniti non deducibili facilmente dalla lettura del codice
Observer
Interfaccia grafica: un componente si ridimensiona e notifica a tutti gli altri di riadattarsi
class
ProxyPlanimetria
implements
InterfacePlanimetria {

private

$path
;

private

$planimetria
;


public function
__construct(
$path
) {

$this
->
path
=
$path
;
}

public function
mostraPlanimetria() {
if (
$this
->
planimetria
== null) {

$this
->
planimetria
=
new
Planimetria(
$this
->
path
);
$this
->
planimetria->
caricaDaDisco() // carica a richiesta
}

$this
->
planimetria
->mostraPlanimetria();
}
}

codice client:

$p1
=
new
ProxyPlanimetria(
"/home/lorenzo/img1.jpg"
);

$p1
->mostraPlanimetria(); //qui esegue il caricamento // loading necessary
.... passa mezz'ora ...

$p1
->mostraPlanimetria(); //qui no, già caricato

Proxy
Strategy
Serve ad applicare ai dati un algoritmo specifico scelto al
run-time.
interface
StrategyPrezzoInterface {

public function
price();
}

abstract class
StrategyPrezzo {

const

PREZZO_BASE
= 0;

const

IVA
= 1.21;

const

PREZZO_CAROSELLO
= 1;

const

PREZZO_TOP
= 20;

const

PREZZO_VETRINA
= 50;
}

class
PrezzoBase
extends
StrategyPrezzo {

public function
getPrezzo() {

return

self
::
PREZZO_BASE
*
IVA
;
}
}

class
PrezzoTop
extends
StrategyPrezzo {

public function
getPrezzo() {

return
(
self
::
PREZZO_BASE
+
self
::
PREZZO_TOP
+
self
::
PREZZO_CAROSELLO
) *
self
::
IVA
}
}

class
PrezzoVetrina
extends
StrategyPrezzo {

public function
getPrezzo() {

return
(
self
::
PREZZO_BASE
+
self
::
PREZZO_VETRINA
+
self
::
PREZZO_CAROSELLO
) *
self
::
IVA
}
}

class
Annuncio {

protected
$pricing
;


public function
__construct(StrategyPrezzoInterface
$pricing
) {

$this-
>
pricing
=
$pricing
;
}


public function
getPrezzo() {

return

$this-
>
pricing
->getPrezzo();
}
}


Strategy
client:
//annuncio base
$annuncio
=
new
Annuncio(
new
PrezzoBase());

//annuncioTop
$annuncio
=
new
Annuncio(
new
PrezzoTop());

//annuncioVetrina
$annuncio
=
new
Annuncio(
new
PrezzoVetrina());
Strategy
Pro:
gli oggetti sono costruiti indipendentemente dagli algoritmi che operano sui dati: facilità di aggiungere algoritmi nuovi
L'implementazione delle strategie può variare senza che il client ne sia a conoscenza
Contro:
L'utilizzatore deve conoscere in anticipo tutte le strategie per istanziare quella corretta.
Strategy

diverse viste degli stessi dati (ex. grafici istogramma, torta ecc..): la modalità di visualizzazione viene scelta con il pattern strategy
Decorator
Tipico caso d'uso:
processing di stream di dati (aggiungo compressione, buffering, etc. come Decorator)
Facade
Il client generico dei webservice su
immobiliare.it prevede di invocare:
buildJson($data)
getToken($user,$password)
sendRequest($json,$token)
La classe facade costruita su tale client espone un solo metodo:
send ($data)
il token, l'utente e il json sono richiesti e assemblati internamente al metodo send(..);
(caso d'uso)
Facade
(caso d'uso)
Nel webservice subito.it
metodi classe subito:
setDescription($description)
setPrice($price)
setCity($cityId)
deleteImages($subitoImageId)
updateImage($image)
sendAd()
classe facade:
updateAnnuncio($idAnnuncio)

(caso d'uso)
Decorator
(caso d'uso)
Nel client dei futuri Webservice di Immobiliare.it è stato decorato il jsonserver per aggiungere header custom che servono a passare info al client
Proxy
(caso d'uso)
Si può usare il proxy quando si vuole controllare l'accesso agli oggetti 'proxati', consentendolo in alcuni casi e negandolo in altri (Protection Proxy):

Risoluzione indirizzi con google: si effettua la richiesta solamente quando l'indirizzo non è già presente in cache


Proxy
(caso d'uso)
(caso d'uso)
Builder
(caso d'uso)
Iniettare negli oggetti che rappresentano le agenzie i vari tipi di contratto.
Factory
(caso d'uso)
Un software che può essere comandato da linea di comando o da interfaccia grafica: il software è l'observed, la gui e la shell sono gli observer
(caso d'uso)
Observer
(caso d'uso)
(caso d'uso)
Procedure di autenticazione differenti: login+password, facebook , google ecc... (viene iniettato il controllore delle credenziali al runtime)
Strategy
(caso d'uso)
E questo è quanto...
Grazie a tutti per l'attenzione!
Silvio
Lorenzo
Perché usarli
Costituiscono un vocabolario tecnico condiviso:
la comunicazione nel team è facilitata perché si parla di soluzioni note che entrano a far parte del vocabolario comune.

I Pattern permettono di parlare ad un più alto livello concettuale: si fa riferimento a nomi che indicano soluzioni anche molto complesse.
Perché usarli
Consentono un processo di progettazione ripetibile da più persone in un team.
Perché usarli
Permettono il riuso di soluzioni
Si adottano soluzioni ottenute dall'esperienza di altri.
Non si reinventa la ruota per i problemi ricorrenti: riduzione a casi noti
Perché usarli
Solidità e flessibilità
Sono delle soluzioni ampiamente testate.
Si sono evoluti in strutture facilmente modificabili (in modo originale o traendo dalla letteratura) rispetto a soluzioni che inizialmente vengono in mente.
Builder
(caso d'uso)
Classe ricerca: instanziata attraverso un builder per iniettare
gli oggetti query MySQL o Solr
SolrQueryBuilder: è la factory degli oggetti SearchRequest che evita che il costruttore di tali oggetti abbia una logica complessa e che debba conoscere l'oggeto SolrServer
Q & A
(facciata)
Patterns of Enterprise Application Architecture
Letture consigliate
Martin Fowler
Applying UML and Patterns
Craig Larman
Enterprise Integration Patterns
Gregor Hohpe, Bobby Woolf
Design Patterns
Gamma, Helm, Johnson, Vlissides
Full transcript