31
Dizajn paterni Decorator, Factory dr Zoran Jeremić [email protected] 1

T 3.8 design paterni (c)

Embed Size (px)

Citation preview

Page 1: T 3.8 design paterni (c)

Dizajn paterniDecorator, Factory

dr Zoran Jeremić[email protected]

1

Page 2: T 3.8 design paterni (c)

DECORATORStrukturni paterni

2

Page 3: T 3.8 design paterni (c)

Opis problema

Kao jedan od vodećih svetskih lanaca sa coffee shop konceptom, Costa Coffee u proseku otvara po pet kafeterija nedeljno, na različitim lokacijama širom sveta.

Zbog tako velikog rasta, neprekidno se trude da obogate svoju ponudu novim napicima.

3

Page 4: T 3.8 design paterni (c)

4

Page 5: T 3.8 design paterni (c)

Opis problema

Osim kafe, moguće je naručiti i priloge, kao što su šlag, mleko, soja, čokolada, i svi oni utiču na cenu, pa ih je potrebno ugraditi u sistem.

5

Page 6: T 3.8 design paterni (c)

Opis problema

Očigledno je dati model komplikovan i težak za održavanje. Šta se dešava kada cena mleka skoči? Šta se deš

Možemo li osnovnoj klasi Beverage dodati promenjlive koje pokazuju da li napitak ima neki dodatak?

6

Page 7: T 3.8 design paterni (c)

Opis problema

7

Page 8: T 3.8 design paterni (c)

Implementacija klasa

Ovakav model značajno smanjuje broj klasa, ali određeni problemi i dalje nisu rešeni. Šta se dešava u slučaju budućih promena (promena cene, novi

prilozi, novi napici)?

8

public class Beverage {double cost() {

//izracunati cenu sa dodacima

}

public class DarkRoast extendsBeverage {

public DarkRoast(){description=“Most Excellent Dark

Roast”;}

double cost() {super.coast();//izracunati cenu tipa kafe

}

Page 9: T 3.8 design paterni (c)

Decorator

Namena Dinamički dodeljuje dodatnu odgovornost objektima. Decorator

obezbeđuje fleksibilnu alternativu proširivanju podklasa zbog proširivanja funkcionalnosti.

Problem Želite da dodate ponašanje ili stanje pojedinačnim objektima u

vreme izvršenja. Nasleđivanje nije moguće jer je statičko i primenjuje se na čitavu klasu.

9

Page 10: T 3.8 design paterni (c)

Primena na opisani problem

Pretpostavimo da kupac želi DarkRoast sa čokoladom (Mocha) i šlagom (Whip)

Uzmite DarkRoast objekat

Dekorišite ga Mocha objektom

Dekorišite ga Whip objektom

Pozovite cost() metodu i koristite delegiranje da bi dodali troškove priloga.

10

Page 11: T 3.8 design paterni (c)

Primena na opisani problem

Započinjemo sa DarkRoast objektom

Kupac je tražio Mocha, tako da kreiramo Mocha objekat tako da obuhvata DarkRoast.

11

Page 12: T 3.8 design paterni (c)

Primena na opisani problem

Kupac takođe želi šlag (Whip), pa kreiramo Whip dekorator i smeštamo Mocha unutar njega.

12

Page 13: T 3.8 design paterni (c)

Izračunavanje cene

13

Page 14: T 3.8 design paterni (c)

Decorator – dijagram klasa

14

Page 15: T 3.8 design paterni (c)

Dijagram klasa kafeterije

15

Page 16: T 3.8 design paterni (c)

Implementacija klasa Beverage i CondimentDecorator

16

public abstract class Beverage {String description=“Unknown Beverage”;

public String getDescription(){return description;

}public abstract double cost();

}

public abstract class CondimentDecorator extends Beverage {public abstract String getDescription();

}

Page 17: T 3.8 design paterni (c)

Implementacija konkretnih komponenti

17

public class Espresso extends Beverage {

public Espresso(){description=“Espresso”;

}public double cost(){

return 1.99;}

}

public class HouseBlend extends Beverage {

public Espresso(){description=“House Blend Coffe”;

}public double cost(){

return 0.89;}

}

Page 18: T 3.8 design paterni (c)

Implementacija konkretnih dekoratora

18

public class Mocha extends CondimentDecorator {Beverage beverage;

public Mocha(Beverage beverage){this.beverage=beverage;

}public String getDescription(){

return beverage.getDescription() + “, Mocha”;}public abstract double cost(){

return 0.20 + beverage.cost();}

}

Page 19: T 3.8 design paterni (c)

Korišćenje dekoratora

19

public class StarbuzzCoffee {public static void main(String args[]) {

Beverage beverage = new Espresso();System.out.println(beverage.getDescription()+ “ $” + beverage.cost());

Beverage beverage2 = new DarkRoast();beverage2 = new Mocha(beverage2);beverage2 = new Mocha(beverage2);beverage2 = new Whip(beverage2);

System.out.println(beverage2.getDescription()+ “ $” + beverage2.cost());

Beverage beverage3 = new HouseBlend();beverage3 = new Soy(beverage3);beverage3 = new Mocha(beverage3);beverage3 = new Whip(beverage3);System.out.println(beverage3.getDescription()+ “ $” + beverage3.cost());

}}

Page 20: T 3.8 design paterni (c)

Decorator - Primenljivost

Za dodavanje odgovornosti pojedinačnim objektima na dinamički i transparentan način, tj. bez uticaja na druge objekte,

Za odgovornosti koje mogu da se povuku,

Kada proširenje pomoću pravljenja podklasa nije praktično.

20

Page 21: T 3.8 design paterni (c)

Decorator - posledice

Prednosti: Veća fleksibilnost od staičkog nasleđivanja, Izbegavaju se klase prebogate karakteristikama visoko u

hijerarhiji.

Nedostaci: Dekorator i njegova komponenta nisu identični. Dekorator služi

kao transparentni omotač, pa prema tome ne bi trebalod a se oslanjate na identitet objekta kada koristite dekoratere.

Mnogo malih objekata. Ako se u projektu mnogo koristi Decorator, dobiće se sistem sastavljen od mnogo sličnih malih objekata. Objekti se razlikuju samo po tome kako su međusobno povezani, a ne prema klasi ili vrednostima promenljivih. U takvom sistemu teško je analizirati greške.

21

Page 22: T 3.8 design paterni (c)

FACTORYPaterni kreiranja

22

Page 23: T 3.8 design paterni (c)

Opis problema

Kada koristimo new mi zapravo instanciramo konkretnu klasu, tako da je to definitivno implementacija a ne interfejs.

Kada imamo skup povezanih konkretnih klasa, često pišemo kod poput ovog:

23

Duck duck = new MallardDuck();

Duck duck;

If (picnic) {duck = new MallardDuck();

} else if (hunting) {duck = new DecoyDuck();

}else if (inBathTub){duck = new RubberDuck();

}

Page 24: T 3.8 design paterni (c)

Opis problema

Kod pisan kroz interfejse će raditi kroz polimorfizam sa bilo kojom novom klasom koja implementira interfejs.

Međutim kada imamo dostra konkretnih klasa, kod se mora menjati dodavanjem novih konkretnih klasa.

24

Page 25: T 3.8 design paterni (c)

Opis problema

25

Pizza orderPizza(){Pizza pizza = new Pizza ();

pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;

}

Zbog fleksibilnostiPizza je abstraktna

klasa

Page 26: T 3.8 design paterni (c)

Opis problema

26

Pizza orderPizza(String type){Pizza pizza = new Pizza ();

pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;

}

if (type.equals(“cheese”)) {pizza = new CheesePizza();

} else if (type.equals(“greek”) {pizza = new GreekPizza();

} else if (type.equals(“pepperoni”) {pizza = new PepperoniPizza();

}

Sada prosleđujemo vrstu pice kao

argument

Na osnovu vrste pice instanciramo

konkretnu klasu i dodeljujemo je

promenljivoj pizza

Page 27: T 3.8 design paterni (c)

Opis problema

27

Pizza orderPizza(String type){Pizza pizza = new Pizza ();if (type.equals(“cheese”)) {

pizza = new CheesePizza();} else if (type.equals(“greek”) {

pizza = new GreekPizza();} else if (type.equals(“pepperoni”) {

pizza = new PepperoniPizza();

pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;

}

Kod se morakonstantno menjati u skladu sa ponudama

picerije

} else if (type.equals(“clam”)) {pizza = new ClamPizza();

} else if (type.equals(“veggie”) {pizza = new VeggiePizza();

}

Page 28: T 3.8 design paterni (c)

Enkapsulacija kreiranja objekta

28

Pizza orderPizza(String type){Pizza pizza = new Pizza ();

pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;

}

if (type.equals(“cheese”)) {pizza = new CheesePizza();

} else if (type.equals(“pepperoni”) {pizza = new PepperoniPizza();

} else if (type.equals(“clam”)) {pizza = new ClamPizza();

} else if (type.equals(“veggie”) {pizza = new VeggiePizza();

}

Page 29: T 3.8 design paterni (c)

Jednostavan pizza factory

29

public class SimplePizzaFactory {

public Pizza createPizza(String type) {Pizza pizza = null;if (type.equals(“cheese”)) {

pizza = new CheesePizza();} else if (type.equals(“pepperoni”)) {

pizza = new PepperoniPizza();} else if (type.equals(“clam”)) {

pizza = new ClamPizza();} else if (type.equals(“veggie”)) {

pizza = new VeggiePizza();}return pizza;

}}

Metodu createPizza() koriste svi klijenti zainstanciranje novih

objekata.

Ovaj kod je još uvek parametrizovan

vrstom pice, kao i u originalnoj

orderPizza() metodi.

Page 30: T 3.8 design paterni (c)

PizzaStore klasa

30

public class PizzaStore {

public Pizza orderPizza(String type) {Pizza pizza;

pizza.prepare();pizza.bake();pizza.cut();

pizza.box();return pizza;

}// other methods here}

SimplePizzaFactory factory;public PizzaStore(SimplePizzaFactory factory) {this.factory = factory;}

pizza = factory.createPizza(type);

PizzaStore klasi se prosleđuje factory kroz

konstruktor

orderPizza() metoda koristi factory da kreira

picu jednostavnim prosleđivanjem tipa pice

Page 31: T 3.8 design paterni (c)

Dijagram klasa

31