Strukturni dizajn paterni Lab vebe Prof dr Angelina
Strukturni dizajn paterni Lab vežbe Prof. dr Angelina Njeguš Redovni profesor na Univerzitetu Singidunum anjegus@singidunum. ac. rs Beograd, 2019/2020.
Adapter
Struktura adaptera objekta Klasa Klijent sadrži postojeću poslovnu logiku aplikacije. Sadrži main metodu. Interfejs klijenta opisuje protokol koje druge klase moraju da prate kako bi sarađivale. Adapter je klasa koja je: • • • sposobna da radi sa oba i klijentom i servisom (Adaptee). implementira interfejs klijenta. prihvata pozive od strane klijenta preko adapter interfejsa i prevodi ih u pozive objekta servisa u formatu koji može da razume. Servis je neka korisna klasa (obično treće strane ili nasleđena klasa). Klijent ne može koristiti direktno ovu klasu jer ima nekompatibilni interfejs.
Primer primene: Audio plejer zadatak § Kratak opis zadatka: Postoji interfejs klijenta Media. Player, koga implementira klasa Audio. Player, koja po difoltu može da reprodukuje audio fajlove u mp 3 formatu. Drugi Adaptee interfejs je Advanced. Media. Player koji može da reprodukuje vlc i mp 4 formate. Ovaj interfejs realizuju klase Vlc. Player i Mp 4 Player. § Cilj je da se omogući da klasa Audio. Player reprodukuje i druge formate. § Rešenje?
Primena Adapter paterna § Kreirati projekat i paket Adapter. Pattern § Kreirati dijagram klasa kao na slici desno § Primeniti adapter patern i povezati (bind-ovati) sa modelom. § Izgenerisati kod § Dopuniti java klase i izvršiti program.
Poređenje konkretnog modela paterna za šablonom adapter paterna
Koraci kreiranja aplikacije § Nakon nacrtanog dijagrama klasa u okviru koga je izvršeno povezivanje (bind-ovanje) sa Adapter paternom, generišite izvorni kod. § Izvorni kod dopunite, prateći sledeće korake: 1. Korak: Kreirajte interfejse tipa Target i Adaptee i njihove klase koje ih implementiraju 2. Korak: Kreirajte klasu tipa Adapter 3. Korak: Kreirati main klasu
Korak 1: Kreirajte interfejse tipa Target i Adaptee i njihove klase koje ih implementiraju § Interfejs tipa Target: Media. Player. java
Korak 1: Kreirajte interfejse tipa Target i Adaptee i njihove klase koje ih implementiraju § Interfejs tipa Adaptee:
Korak 1: Kreirajte interfejse tipa Target i Adaptee i njihove klase koje ih implementiraju § Klase Vic. Player i Mp 4 Player koje implementiraju interfejs tipa Adaptee. § Klasa Vic. Player. java:
Korak 1: Kreirajte interfejse tipa Target i Adaptee i njihove klase koje ih implementiraju § Klasa Mp 4 Player koja implementira interfejs tipa Adaptee:
Korak 2: Kreirajte klasu tipa Adapter Klasa Media. Adapter implementira interfejs Klijenta (Target):
Dopuna koraka 1: Konkretna Target klasa Konkretna target klasa Audio. Player implementira interfejs tipa Target:
Korak 3: Kreirati main klasu § Kreirajte glavnu klasu Adapter. Pattern. Demo u okviru koje ćete prilikom kreiranja uključiti generisanje main metode.
Izvršite aplikaciju Run as Java Application Rezultat aplikacije prikazanog na konzoli:
Decorator
Osnovna struktura Decorator paterna
Primer primene Decorator paterna: Prodaja sladoleda sa dodacima § Kratak opis zadatka: Postoji interfejs Icecream, sa metodama get. Desc() i get. Price(); Klasa Simple. Icecream implementira interfejs Icecream; Apstraktna klasa Icecream. Decorator implementira interfejs Icecream; Dok Nutty i Honey nasleđuju klasu Icecream. Decorator. § Cilj je da se izračuna i prikaže ukupna cena sladoleda sa dodacima koje je klijent poručio. § Rešenje?
Primena Decorator paterna § Kreirati projekat i paket Decorator. Pattern § Kreirati dijagram klasa kao na slici desno § Primeniti Decorator patern i povezati (bind-ovati) sa modelom. § Izgenerisati kod § Dopuniti java klase i izvršiti program.
Poređenje sa šablonom paterna
Koraci kreiranja aplikacije § Nakon nacrtanog dijagrama klasa u okviru koga je izvršeno povezivanje (bind-ovanje) sa Decorator paternom, generišite izvorni kod. § Izvorni kod dopunite, prateći sledeće korake: 1. Korak: Kreirajte interfejs tipa Component (u primeru: Icecream), sa dve metode i to: get. Desc: String i get. Price: double. 2. Korak: Kreirajte klasu/klase tipa Concrete. Component (u primeru: Simple. Icecream) koja implementira klasu Icecream. 3. Korak: Kreirajte apstraktnu klasu tipa Base. Decorator (u primeru: Icecream Decorator). 4. Korak Kreirajte dodatke tzv. Concrete decorators (u zadatku Honey i Nutty). 5. Korak: Kreirati main klasu
Korak 1: Kreirajte interfejs tipa Component § Interfejs tipa Component: Icecream. java public interface Icecream { public String get. Desc(); public double get. Price(); }
Korak 2: Kreirajte klasu/klase tipa Concrete. Component public class Simple. Icecream implements Icecream public String get. Desc() { return "Base icecream: 150"; } public double get. Price() { return 150; } }
Korak 3: Kreirajte apstraktnu klasu tipa Base. Decorator public abstract class Icecream. Decorator implements Icecream { protected Icecream icecream; public Icecream. Decorator(Icecream icecream) { this. icecream=icecream; } public String get. Desc(){ return icecream. get. Desc(); } }
Korak 4: Kreirajte dodatke (Concrete decorators) public class Nutty extends Icecream. Decorator { public Nutty(Icecream icecream) { super(icecream); } public String get. Desc() { return icecream. get. Desc()+", Nutty: 20"; } public double get. Price() { return icecream. get. Price()+20; } }
Honey dodatak: public class Honey extends Icecream. Decorator { public Honey(Icecream icecream) { super(icecream); } public String get. Desc() { return icecream. get. Desc()+", Honey: 20"; } public double get. Price() { return icecream. get. Price()+20; } }
Korak 5: Kreirati main klasu public class Client { public static void main(String[] args) { Icecream icecream = new Simple. Icecream(); icecream = new Honey(icecream); icecream = new Nutty(icecream); System. out. println("Description "+"n"+icecream. get. Desc()); System. out. println("Price: "+ icecream. get. Price()); } }
Rezultat pokretanja aplikacije
Facade
Osnovna struktura paterna The Facade provides convenient access to a particular part of the subsystem’s functionality. It knows where to direct the client’s request and how to operate all the moving parts. The Client uses the facade instead of calling the subsystem objects directly. An Additional Facade class can be created to prevent polluting a single facade with unrelated features that might make it yet another complex structure. Additional facades can be used by both clients and other facades. The Complex Subsystem consists of dozens of various objects. To make them all do something meaningful, you have to dive deep into the subsystem’s implementation details, such as initializing objects in the correct order and supplying them with data in the proper format. Subsystem classes aren’t aware of the facade’s existence. They operate within the system and work with each other directly.
Primer primene Facade paterna: Aplikacija za kreiranje kola § Kratak opis zadatka: Korisnik preko aplikacije za kreiranje željenih kola, može da dodaje željenu opremu, bira model i motor kola. Postoje klase Car. Accessories, Car. Body i Car. Engine, koje imaju odgovarajuće set metode (npr. set. Car. Body()). Klasa Car. Facade sadrži metod create. Car(). § Cilj je da se proveri da li su svi željeni delovi kola podešeni prema zahtevima korisnika. § Rešenje?
Primena Facade paterna § Kreirati projekat i paket Facade. Pattern § Kreirati dijagram klasa kao na slici desno § Primeniti Facade patern i povezati (bind-ovati) sa modelom. § Izgenerisati kod § Dopuniti java klase i izvršiti program.
Kod aplikacije public class Car. Accessories { public void set. Car. Accessories() { System. out. println("Car accesories are set. "); } } public class Car. Body { public void set. Car. Body() { System. out. println("Car body is set. "); } } public class Car. Engine { public void set. Car. Engine() { System. out. println("Car Engine is set. "); } }
Kod Car. Facade public class Car. Facade { private Car. Engine engine; private Car. Body body; private Car. Accessories accessories; public Car. Accessories get. Car. Accessories() { return accessories; } public void set. Car. Accessories(Car. Accessories accessories) { this. accessories = accessories; } public Car. Body get. Car. Body() { return body; } public void set. Car. Body(Car. Body body) { this. body = body; } public Car. Engine get. Car. Engine() { return engine; } public void set. Car. Engine(Car. Engine engine) { this. engine = engine; } public void create. Car() { System. out. println("Creating a car. . . "); engine. set. Car. Engine(); body. set. Car. Body(); accessories. set. Car. Accessories(); System. out. println("Your car is ready. "); } public Car. Facade() { this. engine= new Car. Engine(); this. body=new Car. Body(); this. accessories=new Car. Accessories(); } }
Kod Client aplikacije i rezultat public class Client { public static void main(String[] args) { Car. Facade facade = new Car. Facade(); facade. create. Car(); } }
Bridge
Struktura 1. Apstrakcija – visok nivo kontrole logike sistema. Oslanja se na objekte implementacije koje izvršavaju poslove nižeg nivoa. 4. Prerađene apstrakcije - rade sa različitim implementacijama preko opšteg interfejsa implementacije. 5. Klijent je obično radi sa apstrakcijom i na njemu je da poveže objekte apstrakcije sa jednim od objekata implementacije. 2. Implementacija – deklariše interfejs koji je zajednički za sve konkretne implementacije. Jedna apstrakcija može komunicirati sa objektom implementacije samo preko metoda koje su deklarisane ovde. 3. Konkretne implementacije – sadrže kod koji je specifičan za određenu platformu.
Vežba: Primenite Bridge patern na model Banke
Rešenje
Let’s code U RSA alatu kreirajte projekat i primenite Bridge patern:
Generišite kod i dopunite klase § Korak 1: Kreirajte Bridge implementator interfejs: Account. java public interface Account { public Account open. Account(); public void account. Type(); } § Korak 2: Kreirajte konkretne klase koje implementiraju Account interfejs: public class Current. Account implements Account { public Account open. Account() { System. out. println("OPENED: CURRENT ACCOUNT "); return new Current. Account(); } public void account. Type() { System. out. println(" It is a CURRENT Account "); } } public class Saving. Account implements Account { public Account open. Account() { System. out. println("OPENED: SAVING ACCOUNT "); return new Saving. Account(); } public void account. Type() { System. out. println(" It is a SAVING Account "); } }
Dopunite klase sa kodom § Korak 3: Kreirajte apstraktnu klasu Bank koja koristi Account interfejs. public abstract class Bank { //Composition with implementor protected Account implementor; public Account get. Implementor() { return implementor; } public void set. Implementor(Account implementor) { this. implementor = implementor; } public Bank(Account account) { this. implementor=account; } abstract Account open. Account(); }
Dopunite klase sa kodom § Korak 4: Kreirajte konkretne klase koje nasleđuju apstraktnu klasu Banka. public class Hdf. Bank extends Bank { public Hdf. Bank(Account account) { super(account); } @Override Account open. Account() { System. out. println("Open your account with HDFC Bank. "); return implementor; } } public class Icici. Bank extends Bank { public Icici. Bank(Account account) { super(account); } @Override Account open. Account() { System. out. println("Open your account with ICICI Bank. "); return implementor; } }
Kreirajte glavnu klasu i izvršite kod § Glavna klasa: public class Bridge. Pattern. Main { public static void main(String[] args) { Bank icici=new Icici. Bank(new Current. Account()); Account current=icici. open. Account(); current. account. Type(); Bank hdfc=new Hdf. Bank(new Saving. Account()); Account saving = hdfc. open. Account(); saving. account. Type(); } } § Rezultat:
Composite
Struktura 1. Interfejs Component opisuje operacije koje su zajedničke za jednostavne, ali i skložene elemente stabla. 2. List (Leaf) je osnovni element stabla koji nema pod elemenata. Obično, komponente lista rade dosta posla, jer nemaju nikome da delegiraju. 4. Klijent radi sa svim elementima kroz interfejs komponente. Kao rezultat, klijent može da radi na isti način bilo da su elementi stabla jednostavni ili složeni. 3. Kointejner (Container ili Composite) je element koji ima pod elemente: lišće ili druge kontejnere. Kontejner ne zna konkretne klase svoje dece, a preko zajedničkog interfejsa radi sa svim pod elementima. Kada dobije zahtev, kontejner delegira posao njegovim pod elementima, obrađuje među rezultate i vraća finalni rezultat klijentu.
Struktura sa više elemenata Pretpostavljene implementacije metoda za upravljanje komponentama
Vežba: Primenite Composite patern Korak 1: Kreirati dijagram klasa i povezati klase sa Composite paternom • Osnovna komponenta Composite paterna definiše zajedničke metode za listove i kompozitne klase. • U ovom primeru klasa Shape će imati metod draw(String fill. Color) kako bi nacrtala različite oblike (koji predstavljaju listove) sa datom bojom.
Korak 2: Izgenerisati kod i dopuniti klase Apstraktna klasa Shape. java public abstract class Shape { public abstract void draw(String fill. Color); private Shape m_parent; public Shape get. Parent() { return m_parent; } public void set. Parent(Shape a_parent) { m_parent = a_parent; } public abstract Drawing get. Composite(); }
Listovi Component klase Shape: § Triangle. java public class Triangle extends Shape { public void draw(String fill. Color) { System. out. println("Drawing Triangle with color "+fill. Color); } public Drawing get. Composite() { return null; } } § Circle. java public class Circle extends Shape { public void draw(String fill. Color) { System. out. println("Drawing Circle with color "+fill. Color); } public Drawing get. Composite() { return null; } }
Kompozitna klasa Drawing import java. util. *; public class Drawing extends Shape { private List<Shape> shapes; public List<Shape> get. Shapes() { return shapes; } public void set. Shapes(List<Shape> shapes) { this. shapes = shapes; } public void draw(String fill. Color) { for(Shape sh: shapes){ sh. draw(fill. Color); } } public void add(Shape s) { this. shapes. add(s); } public void remove(Shape s) { shapes. remove(s); } public void clear() { System. out. println("Clearing all the shapes from drawing"); this. shapes. clear(); }
Nastavak prethodnog koda public Drawing get. Composite() { return this; } public Drawing() { shapes = new java. util. Array. List<Shape>(); } public synchronized void add. Child(Shape a_component) { synchronized (a_component) { shapes. add(a_component); a_component. set. Parent(this); } } public Shape get. Child(int a_child. Index) { return (Shape) shapes. get(a_child. Index); } public synchronized void remove. Child(Shape a_component) { synchronized (a_component) { if (this == a_component. get. Parent()) { a_component. set. Parent(null); } shapes. remove(a_component); } } }
Glavna metoda Test. Composite. Pattern public class Test. Composite. Pattern { public static void main(String[] args) { Shape tri=new Triangle(); Shape cir=new Circle(); Drawing drawing=new Drawing(); drawing. add(tri); drawing. add(cir); drawing. draw("Red"); drawing. clear(); drawing. add(tri); drawing. add(cir); drawing. draw("Green"); } }
Rezultat izvršavanja koda
- Slides: 54