1 / 33

Μεθοδολογίες Προγραμματισμού ΙΙ Σχεδιαστικά Πρότυπα (2)

Μεθοδολογίες Προγραμματισμού ΙΙ Σχεδιαστικά Πρότυπα (2). Παναγιώτης Σφέτσος , PhD http://aetos.it.teithe.gr/~sfetsos/ sfetsos@it.teithe.gr. Ταξινόμηση Σχεδιαστικών Προτύπων. ΥπερΚλάσεις – Αφηρημένες και Διεπαφές (1/11). Σχεδιασμός ενός ηλεκτρονικού παιχνιδιού με πάπιες που….

asher-wells
Download Presentation

Μεθοδολογίες Προγραμματισμού ΙΙ Σχεδιαστικά Πρότυπα (2)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Μεθοδολογίες Προγραμματισμού ΙΙ Σχεδιαστικά Πρότυπα (2) Παναγιώτης Σφέτσος, PhD http://aetos.it.teithe.gr/~sfetsos/ sfetsos@it.teithe.gr

  2. Ταξινόμηση Σχεδιαστικών Προτύπων Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  3. ΥπερΚλάσεις – Αφηρημένες και Διεπαφές (1/11) Σχεδιασμός ενός ηλεκτρονικού παιχνιδιού με πάπιες που…. • Κάθε υποκλάση υλοποιεί διαφορετικά την αφηρημένη μέθοδο display() (διαφορετικές • πάπιες) • Κάθε νέα υποκλάση κληρονομεί από την κλάση Duck… • Τι θα συμβεί αν θέλουμε να προσθέσουμε μια νέα μέθοδο fly(); Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  4. ΥπερΚλάσεις – Αφηρημένες και Διεπαφές (2/11) Όλες οι υποκλάσεις κληρονομούν την fly(). Όλες οι πάπιες πετούν; Τι θα γίνει αν προστεθεί μια νέα υποκλάση από πάπιες που δεν πετούν; Φορτώσαμε συμπεριφορά (fly()) που δεν μπορούν να υλοποιήσουν όλες οι υποκλάσεις (διαφορετικές πάπιες). Προσθέτοντας μια νέα υποκλάση τηνRubberDuck, αυτές οι πάπιες δεν κάνουν quack(). Μία λύση να υπερσκελίσουμε(override)την quack() σε squeak(). Το ίδιο με την fly(), με υπερσκέλισηνα μην κάνει τίποτε. ΚΑΚΗ ΣΧΕΔΙΑΣΗ !!!!! Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  5. ΥπερΚλάσεις – Αφηρημένες και Διεπαφές (3/11) • Μια λύση να ξεχωρίσουμε συμπεριφορές κάνοντας τες διεπαφές, εδώ τις συμπεριφορές • fly και quack. • Οι διεπαφές Flyable και Quackableέχουν αντίστοιχα μια μέθοδο fly() και μια μέθοδο • quack()για να υλοποιούνται από τις υποκλάσεις που τις χρειάζονται. • Μερική λύση αλλά καταστρέφεται η επαναχρησιμοποίηση του κώδικα (reuse)για αυτές • τις συμπεριφορές. Κάποιο σχεδιαστικό πρότυπο; (αφήστε το για μετά). • Ας πάρουμε την 1η καλή σχεδιαστική αρχή της αντκειμενοστρέφειας: • Πάρε όλη την συμπεριφορά που μεταβάλλεται και ενθυλάκωσέ την (encapsulate), • έτσι δεν θα επηρεάζει τον υπόλοιπο κώδικα σου. Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  6. ΥπερΚλάσεις – Αφηρημένες και Διεπαφές (4/11) • Ορίζουμε δύο διεπαφές τις FlyBehaviorκαι QuackBehaviorμε τις αντίστοιχες • υποκλάσεις να υλοποιούν συγκεκριμένες συμπεριφορές. • Έτσι: • α) και άλλες υποκλάσεις μπορούν να χρησιμοποιήσουν αυτές τις συμπεριφορές, δεν είναι • κρυμμένες πλέον στην κλάση Duck. • β) μπορούμε να προσθέσουμε οποιαδήποτε άλλη συμπεριφορά χωρίς αλλαγές στην κλάση • Duck ή στις κλάσεις συμπεριφορών. • Αρκεί στην κλάση Duck να προσθέσουμε δύο μεταβλητές που να αναφέρονται στις δύο συμπεριφορές: Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  7. ΥπερΚλάσεις – Αφηρημένες και Διεπαφές (5/11) public abstract class Duck { FlyBehaviorflyBehavior; QuackBehaviorquackBehavior; public Duck() {} abstract void display(); public void performFly() {flyBehavior.fly();} public void performQuack() {quackBehavior.quack();} public void swim() {System.out.println("Kolympa...."); }} public class MallardDuck extends Duck { public MallardDuck() { quackBehavior = new Quack(); flyBehavior= new FlyWithWings();} public void display() {System.out.println("Agriohina...."); }} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  8. ΥπερΚλάσεις – Αφηρημένες και Διεπαφές (6/11) public interface FlyBehavior {public void fly();} public class FlyWithWings implements FlyBehavior { public void fly(){System.out.println("Petaei...");}} public class FlyNoWay implements FlyBehavior { public void fly(){System.out.println("den petaei...");}} public interface QuackBehavior {public void quack();} public class Quack implements QuackBehavior { public void quack(){System.out.println("quack..quack");}} public class MuteQuack implements QuackBehavior { public void quack(){System.out.println("siopi..tipote");}} public class Squeak implements QuackBehavior { public void quack(){System.out.println("tsirida...");}} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  9. ΥπερΚλάσεις – Αφηρημένες και Διεπαφές (7/11) class MiniDuckSimulator { public static void main(String[] args) { Duck mallard = new MallardDuck(); mallard.performQuack(); mallard.performFly(); }} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  10. ΥπερΚλάσεις – Αφηρημένες και Διεπαφές (8/11) Αν προσθέσουμε δύο μεθόδους setterστην κλάση Duck για τις συμπεριφορές fly καιquak τις: public void setFlyBehavior(FlyBehaviorfb) {flyBehavior = fb;} public void setQuackBehavior(QuackBehaviorqb) {QuackBehavior = qb;} Τότε μπορούμε να αλλάξουμε δυναμικά μια συμπεριφορά (on the fly). Αρκεί να κάνουμε τις παρακάτω αλλαγές: Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  11. ΥπερΚλάσεις – Αφηρημένες και Διεπαφές (9/11) 1) Προσθέσουμεμια νέα κλάσηπάπιας την ModelDuck: public class ModelDuck extends Duck { public ModelDuck() { quackBehavior = new Quack(); flyBehavior= new FlyNoWay();} public void display() {System.out.println(“Model papia...."); }} 2) Και μια νέα συμπεριφορά την FlyRocketPowered : public class FlyRocketPoweredimplements FlyBehavior { public void fly(){System.out.println(“petaei san piravlos..");}} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  12. ΥπερΚλάσεις – Αφηρημένες και Διεπαφές (10/11) Αλλάζουμε την εκτέλεση: class MiniDuckSimulator { public static void main(String[] args) { Duck mallard = new MallardDuck(); mallard.performQuack(); mallard.performFly(); Duck model = new ModelDuck(); model.performFly(); model.setFlyBehavior(new FlyRocketPowered()); model.performFly(); }} Αλλάζει δυναμικά η συμπεριφορά: Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  13. Ενθυλακωμένες Συμπεριφορές (encapsulated) (11/11) Τελικά εκτελέσαμε το σχεδιαστικό πρότυπο Strategy (Στρατηγική): Διαφορετικοί αλγόριθμοι υλοποιούνται σαν συγκεκριμένες υποκλάσεις της διασύνδεσης – διεπαφής. Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  14. Factory Method (Εργοστάσιο) (1/7) Κατηγορία:Creational Σκοπός:Δημιουργία στιγμιοτύπων κλάσεων με τις υποκλάσεις να αποφασίζουν για το ποια θα χρησιμοποιηθεί για τη δημιουργία του στιγμιοτύπου. Ο πελάτης δεν γνωρίζει και δεν ασχολείται με την δημιουργία των στιγμιοτύπων. Συνώνυμα: virtual constructor Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  15. Factory Method (Εργοστάσιο) (2/7) Λειτουργία: Ο πελάτης (client) ζητά από τoFactory την δημιουργία ενός στιγμιότυπου τύπου product. Το Factory το δημιουργεί και το επιστρέφει στον πελάτη. Ο πελάτης δεν γνωρίζει και δεν ασχολείται με τον τρόπο δημιουργίας και αρχικοποίησης του στιγμιοτύπου. Η κλάση xμε τις υποκλάσεις xyκαι xz. Η Factory αποφασίζει ποια υποκλάση (στιγμιότυπο) θα επιστρέψει ανάλογα με τις παραμέτρους που ορίζονται. Η μέθοδος getClass()με παράμετρο abcεπιστρέφει μια υποκλάση της x. Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  16. Factory Method (Εργοστάσιο) (3/7) • Γιατί όχι η χρήση του τελεστή new;π.χ. Pelatispelatis = new Pelatis(code, AKM,…,); • οποιαδήποτε αλλαγή στην κλάση Pelatis, θα επιφέρει αλλαγές και στις κλάσεις που • εξαρτώνται από αυτήν (δομητής, κώδικας, κλπ.). Παραβίαση της αρχής της • Αντιστροφής των Εξαρτήσεων (όχι πάντα, π.χ. μια μόνο κλάση). • κώδικας με χρήση πολλών ifelse ή switch – εντολών για την δημιουργία των • αντικειμένων, στοιχεία που υποδηλώνουν κακή εφαρμογή των αρχών του • αντικειμενοστρεφούς προγραμματισμού, καθώς δυσχεραίνουν τη συντήρηση του • λογισμικού. • υλοποιούμε αφηρημένες κλάσεις ή διεπαφές. Δεν εξαρτόμαστε από συγκεκριμένες • κλάσεις. Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  17. Factory Method (Εργοστάσιο) (4/7) Δύο παραλλαγές: 1η Η Factory είναι απλή κλάση.2η Η Factory είναι abstract ή interface. Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  18. Factory Method (Εργοστάσιο) (5/7) Η Factory είναι απλή κλάση abstract class Mammals { public abstract String VgazoVolta(); } class Cat extends Mammals { public String VgazoVolta() { return "Thapavvolta tin gata“; }} class Dog extends Mammals { public String VgazoVolta() { return "Thapavvolta ton skylo"; }} class MammalsFactory { public static Mammals getMammalObject(String name) { if (name.equalsIgnoreCase("gata")){ return new Cat(); } else { return new Dog(); } }} class FactoryClient { public static void main(String args[]) { MammalsFactory mf = new MammalsFactory(); System.out.println(mf.getMammalObject("skylos").VgazoVolta()); }} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  19. Factory Method (Εργοστάσιο) (6/7) Η Factory είναι κλάση abstract - ή interface –(1/2): interface Product { } class ConcreteProduct implements Product { } abstract class Factory { public void anOperation() { Product product = factoryMethod(); System.out.println("3-dimiourgia antik. product kalontas tin factoryMethod() tisConcreteFactory-> "); System.out.println("Product product = factoryMethod();"); System.out.println("To antikeimeno product dimiourgithike"); } protected abstract Product factoryMethod(); } class ConcreteFactory extends Factory { protected Product factoryMethod() { return new ConcreteProduct(); }} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  20. Factory Method (Εργοστάσιο) (7/7) Η Factory είναι abstract - ή interface κλάση – (2/2): class Client { public static void main( String arg[] ) { System.out.println("1- dimiourgia antik. tis ConcreteFactory->"); System.out.println("Factory creator = new ConcreteFactory();"); System.out.println(); System.out.println(); Factory Factory = new ConcreteFactory(); System.out.println("2- klisi tis anOperation(), tis Factory, gia dhmiourgia antik. typou product-> "); System.out.println("Factory.anOperation();"); System.out.println(); System.out.println(); Factory.anOperation(); }} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  21. Abstract Factory(Αφηρημένο Εργοστάσιο) (1/6) Κατηγορία:Creational Σκοπός:Η παροχή μιας διασύνδεσης για τη δημιουργία οικογενειών συσχετιζόμενων ή εξαρτημένων αντικειμένων χωρίς να προσδιορίζεται η συγκεκριμένη κλάση τους. Συνώνυμα: super factory, factory of factories Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  22. Abstract Factory(Αφηρημένο Εργοστάσιο) (2/6) • Το πρότυπο αυτό αποτελεί ένα υψηλότερο επίπεδο αφαίρεσηςαπό το Factory. • Επιστρέφει μια από πολλές συσχετιζόμενες κλάσεις,κάθε μια από τις οποίες • μπορεί να επιστρέψει ένα ή περισσότερα αντικείμενα, ανάλογα με την • απαίτηση του πελάτη. Δηλαδή το Abstract Factory είναι ένα Factory- • αντικείμενοπου επιστρέφει ένα ή περισσότερα Factories. • Τα ονόματα των κλάσεων είναι κρυμμένα από τον πελάτη (από το Factory). • Αυτό οδηγεί στην εύκολη αλλαγή ή ανταλλαγή των οικογενειών των • αντικειμένων. • Είναι δυνατή η προσθήκη επί πλέον μεθόδων σε κάποιες από τις υποκλάσεις. Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  23. Abstract Factory(Αφηρημένο Εργοστάσιο) (3/6) AbstractFactory-διασύνδεση για λειτουργίες δημιουργίας αφηρημένων - products. ConcreteFactory-υλοποιεί λειτουργίες για την δημιουργία συγκεκριμένων - products. AbstractProduct - διασύνδεση για τον τύπο των αντικειμένων - product. Product-το product που θα δημιουργηθεί από το αντίστοιχο ConcreteFactory.Υλοποιεί την διασύνδεση AbstractProduct. Client-χρησιμοποιεί τις διασυνδέσεις που ορίζουν οι κλάσεις AbstractFactoryκαι AbstractProduct. Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  24. Abstract Factory(Αφηρημένο Εργοστάσιο) (4/6) Η κλάση AbstractFactoryκαθορίζει το προς δημιουργία αντικείμενο, το δημιουργεί, και επιστρέφει ένα αφηρημένο δείκτη σε αυτό το αντικείμενο. Ο πελάτης δεν γνωρίζει τίποτε για τον τύπο του αντικειμένου. Το αντικείμενο δημιουργείται από το Factory και ο πελάτης έχει πρόσβαση μόνο μέσω της αφηρημένης διασύνδεσης: abstract class AbstractProductA{ public abstract void operationA1(); public abstract void operationA2();} class ProductA1 extends AbstractProductA{ ProductA1(String arg){ System.out.println("To product einai: "+arg);} public void operationA1() { }; public void operationA2() { };} class ProductA2 extends AbstractProductA{ ProductA2(String arg){ System.out.println("To product einai: "+arg);} public void operationA1() { }; public void operationA2() { };} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  25. Abstract Factory(Αφηρημένο Εργοστάσιο) (5/6) abstract class AbstractFactory{ abstract AbstractProductAcreateProductA(); abstract AbstractProductBcreateProductB();} class ConcreteFactory1 extends AbstractFactory{ AbstractProductAcreateProductA() { return new ProductA1("ProductA1");} AbstractProductBcreateProductB() { return new ProductB1("ProductB1");}} class ConcreteFactory2 extends AbstractFactory{ AbstractProductAcreateProductA(){ return new ProductA2("ProductA2");} AbstractProductBcreateProductB(){ return new ProductB2("ProductB2");}} //Dimiourgia toy Factory class FactoryMaker{ private static AbstractFactorypf=null; static AbstractFactorygetFactory(String choice){ if(choice.equals("a")){ pf=new ConcreteFactory1(); }else if(choice.equals("b")){ pf=new ConcreteFactory2(); } return pf; }} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  26. Abstract Factory(Αφηρημένο Εργοστάσιο) (6/6) class AbstactFactoryClient{ public static void main(String args[]){ AbstractFactorypf=FactoryMaker.getFactory("a"); AbstractProductA product=pf.createProductA(); AbstractProductB product1=pf.createProductB(); System.out. println(); AbstractFactory pf2=FactoryMaker.getFactory("b"); AbstractProductA product2=pf2.createProductA(); AbstractProductB product3=pf2.createProductB(); }} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  27. “Μέθοδος Υπόδειγμα” (Template Method) (1/7) Κατηγορία:Behavioral Σκοπός:Ορίζει τον σκελετό ενός αλγορίθμου σε μια λειτουργία, αφήνοντας διαφορετικές υλοποιήσεις στις παράγωγες κλάσεις. Δηλαδή, το πρότυπο επιτρέπει στις παράγωγες κλάσεις να επαναορίσουν ορισμένα βήματα του αλγορίθμου χωρίς να αλλάξουν τη δομή του. Συνώνυμα:- Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  28. “Μέθοδος Υπόδειγμα” (Template Method) (2/7) • Επιλύει ένα παρόμοιο πρόβλημα με αυτό του προτύπου "Στρατηγική". • Στόχος:ο διαχωρισμός ενός γενικού αλγορίθμου από συγκεκριμένες • υλοποιήσεις. • Χρησιμοποιείται για τονορισμό των αμεταβλήτων τμημάτων και τη μετάθεση • της υλοποίησης των μεταβλητών τμημάτων του αλγορίθμου σε παράγωγες • κλάσεις. • Στο πρότυπο “Μέθοδος Υπόδειγμα” εφαρμόζεται ο μηχανισμός της • κληρονομικότηταςκαι πολυμορφισμού, ενώ στη “Στρατηγική”η μεταφορά • αρμοδιότητας σε ένα άλλο αντικείμενο μέσω της διαβίβασης μηνυμάτων • (delegation),. • Πολύ συχνά οι σχεδιαστές και προγραμματιστές αντικειμενοστρεφούς • λογισμικού χρησιμοποιούν το πρότυπο, ακόμα και αν δεν γίνεται αντιληπτό • ως ξεχωριστή τεχνική. Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  29. “Μέθοδος Υπόδειγμα” (Template Method) (3/7) Παράδειγμα 1ο: Για να δώσει ένα δάνειο μια τράπεζα σε ένα πελάτη θα κάνει πολλούς ελέγχους για να διαπιστώσει αν ο πελάτης είναι αξιόπιστος, π.χ. checkBank(), checkCredit(), checkLoan(), checkStock(), checkIncome(), κλπ. Θα χρησιμοποιήσουμε ένα πρότυπο “Μέθοδος Υπόδειγμα” για τους ελέγχους αυτούς στην αφηρημένη κλάση CheckBackground και την υλοποίηση στις υποκλάσεις. abstract class CheckBackground { public abstract void checkBank(); public abstract void checkCredit(); public abstract void checkLoan(); public abstract void checkStock(); public abstract void checkIncome(); //template method public void check() { checkBank(); checkCredit(); checkLoan(); checkStock(); checkIncome();}} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  30. “Μέθοδος Υπόδειγμα” (Template Method) (4/7) class LoanApp extends CheckBackground { private String name; public LoanApp(String name) {this.name = name;} public String getName() {return name;} public void checkBank() {System.out.println("check bank..."); } public void checkCredit(){System.out.println("check credit..."); } public void checkLoan() {System.out.println("check loan..."); } public void checkStock() {System.out.println("check stock values..."); } public void checkIncome(){System.out.println("check family income..."); }} class TestTemplateMethod { public static void main(String[] args) { LoanAppmortgageClient = new LoanApp("Nikas Nikos"); System.out.println("\nAxiopistiapelati: " + mortgageClient.getName()); mortgageClient.check(); LoanAppequityloanClient = new LoanApp("VasileiouVasilis"); System.out.println("\nAxiopistiapelati: " + equityloanClient.getName()); equityloanClient.check(); }} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  31. “Μέθοδος Υπόδειγμα” (Template Method) (5/7) Η υλοποίηση γίνεται στην παραγόμενη κλάση LoanApp. Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  32. “Μέθοδος Υπόδειγμα” (Template Method) (6/7) Παράδειγμα 2ο (Πολυμορφισμός): Πρόσθεση διαφορετικού τύπου αριθμών π.χ. int, double, κλπ. Προσοχή πρέπει να χρησιμοποιηθεί castingγια να πάρουμε σωστά αποτελέσματα. abstract class Prosthesi { public abstract double prosthesi(double d1, double d2); //template method } class ProsthesiAnyTypeNumber extends Prosthesi { public double prosthesi(double d1, double d2) { return d1 + d2; }} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

  33. “Μέθοδος Υπόδειγμα” (Template Method) (7/7) class TestAdd { public static void main(String[] args) { double d1 = 10.5, d2 = 9.5; float f1 = 11.5f, f2 = 12.5f; long l1 = 1, l2 = 2; int i1 = 3, i2 = 4; short s1 = 7, s2 = 8; byte b1 = 5, b2 = 6; ProsthesiAnyTypeNumberaddNumber = new ProsthesiAnyTypeNumber(); System.out.println(addNumber.prosthesi(d1,d2)); System.out.println((float)addNumber.prosthesi(f1,f2)); System.out.println((long)addNumber.prosthesi(l1,l2)); System.out.println((int)addNumber.prosthesi(i1,i2)); System.out.println((short)addNumber.prosthesi(s1,s2)); System.out.println((byte)addNumber.prosthesi(b1,b2)); }} Παναγιώτης Σφέτσος, Μεθοδολογίες Προγραμματισμού ΙΙ

More Related