Πρότυπα Σχεδίασης. Design Patterns

Σχετικά έγγραφα
Πρότυπα Σχεδίασης. Design Patterns

Bridge (Γέφυρα) Πρότυπα Σχεδίασης

ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΕΦΗΣ ΑΝΑΛΥΣΗ Πρότυπα Σχεδίασης. Ιωάννης Σταμέλος Βάιος Κολοφωτιάς Πληροφορική

ΠΟΛΥΜΟΡΦΙΣΜΟΣ. 4.1 Κληρονομικότητα και Αρχή της Υποκατάστασης

public void printstatement() { System.out.println("Employee: " + name + " with salary: " + salary);

Αντικειμενοστρεφής Προγραμματισμός

Διαγράμματα Κλάσεων στη Σχεδίαση

ΠΡΟΤΥΠΑ ΣΧΕΔΙΑΣΗΣ. 6.1 Εισαγωγή

Κλάσεις στη Java. Παύλος Εφραιμίδης. Java Κλάσεις στη Java 1

Κλάσεις στη Java. Στοίβα - Stack. Δήλωση της κλάσης. ΗκλάσηVector της Java. Ηκλάση Stack

Οντοκεντρικός Προγραμματισμός ΦΡΟΝΤΙΣΤΗΡΙΟ JAVA

Εισαγωγή στον Αντικειμενοστρέφή Προγραμματισμό Διάλεξη #13

Αντικειµενοστραφής Προγραµµατισµός

Εισαγωγή στον Αντικειμενοστρέφή Προγραμματισμό Διάλεξη #12

Η κατασκευή αντικειμένων της κλάσης Student μπορεί να πραγματοποιηθεί είτε στη main είτε σε οποιαδήποτε μέθοδο κλάσης:

Διάγραμμα Κλάσεων. Class Diagram

Το πρόγραμμα HelloWorld.java. HelloWorld. Κλάσεις και Αντικείμενα (2) Ορισμός μιας Κλάσης (1) Παύλος Εφραιμίδης pefraimi <at> ee.duth.

Από τη UML στον Κώδικα. Μέρος Β

Ορισµός Νήµα (thread) είναι µια ακολουθιακή ροή ελέγχου (δηλ. κάτι που έχει αρχή, ακολουθία εντολών και τέλος) σ ένα

ΠΤΥΧΙΑΚΗ ΕΡΓΑΣΙΑ Αξιολόγηση των Σχεδιαστικών Προτύπων και της Ποιότητας του Λογισμικού μέσω Μετρικών, στις Περιπτώσεις Προσθήκης Λειτουργικότητας και

Εργαστήριο Τεχνολογίας Λογισμικού και Ανάλυσης Συστημάτων - 4 ο Εργαστήριο -

Οντοκεντρικός Προγραμματισμός ΦΡΟΝΤΙΣΤΗΡΙΟ JAVA

Wrapper Classes, Abstract Classes and Interfaces

Κλάσεις και Αντικείµενα

Κληρονομικότητα. Παύλος Εφραιμίδης pefraimi <at> ee.duth.gr. Java Κληρονομικότητα 1

class object Database Database Item Item [sub-typing and polymorphism] MusicCD Video MusicCD Video

Εισαγωγή στον Αντικειμενοστρεφή Προγραμματισμό Διάλεξη #2

Εισαγωγή στον Προγραµµατισµό, Αντώνιος Συµβώνης, ΣΕΜΦΕ, ΕΜΠ,, Slide 6

Εαρινό. Ύλη εργαστηρίου, Ασκήσεις Java

Δομημένος Προγραμματισμός

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κληρονομικότητα

Αντικειμενοστρέφεια. Henri Matisse, Harmony in Red, Κωστής Σαγώνας Νίκος Παπασπύρου

2.1 Αντικειµενοστρεφής προγραµµατισµός

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Πολυμορφισμός Αφηρημένες κλάσεις Interfaces (διεπαφές)

2 Ορισμός Κλάσεων. Παράδειγμα: Μηχανή για Εισιτήρια. Δομή μιας Κλάσης. Ο Σκελετός της Κλάσης για τη Μηχανή. Ορισμός Πεδίων 4/3/2008

Εισαγωγή στη Σχεδίαση Λογισμικού

ΑΠΛΗ ΚΛΗΡΟΝΟΜΙΚΟΤΗΤΑ

Αντικειμενοστραφής Προγραμματισμός

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Πολυμορφισμός Αφηρημένες κλάσεις Interfaces (διεπαφές)

Από τη UML στον Κώδικα. Μέρος Α

Σύνθεση και Κληρονομικότητα

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Πολυμορφισμός Αφηρημένες κλάσεις Interfaces (διεπαφές)

Ειδικά Θέματα Προγραμματισμού

Αντικειμενοστρεφής Προγραμματισμός

ΕΡΓΑΣΙΕΣ ΟΝΤΟΚΕΝΤΡΙΚΟΥ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Κλάσεις. Τροποποιητές, ιασυνδέσεις, Πακέτα. Τροποποιητές ελέγχου προσπέλασης µεταβλητών και µεθόδων

HelloWorld. Παύλος Εφραιμίδης. Java Το πρόγραμμα HelloWorld 1

Παύλος Εφραιµίδης. Java. Κληρονοµικότητα

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αντικείμενα ως ορίσματα

3 Αλληλεπίδραση Αντικειμένων

Προγραμματισμός Ι (ΗΥ120)

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κληρονομικότητα

Προγράμματα με δομή Κληρονομικότητας

Εφαρμογή Μεθοδολογίας ICONIX

Τεχνολογίες Υλοποίησης Αλγορίθµων

Ανάλυση Πληροφοριακών Συστημάτων. «Βασικές Έννοιες Αντικειμενοστρεφούς Προγραμματισμού Διαγράμματα κλάσεων» Βασίλειος Καρακόιδας

Εργαστήριο 02: Προγραμματισμός με Γενικούς Τύπους (JAVA Generics) ΕΠΛ231 Δομές Δεδομένων και Αλγόριθμοι

I (JAVA) Ονοματεπώνυμο: Α. Μ.: Δώστε τις απαντήσεις σας ΕΔΩ: Απαντήσεις στις σελίδες των ερωτήσεων ΔΕΝ θα ληφθούν υπ όψην.

Βασικά της γλώσσας JAVA

ΑΤΕΙ ΘΕΣΣΑΛΟΝΙΚΗΣ ΤΜΗΜΑ ΜΗΧΑΝΙΚΩΝ ΠΛΗΡΟΦΟΡΙΚΗΣ Αλγοριθμική και Προγραμματισμός. Παναγιώτης Σφέτσος

Εισαγωγή σε αντικειμενοστραφή concepts. Και λίγη C#

Αντικειµενοστρεφής Προγραµµατισµός

ΣΧΕ ΙΑΣΗ ΑΝΤΙΚΕΙΜΕΝΩΝ ΜΕ ΑΡΜΟ ΙΟΤΗΤΕΣ. Ορισµός σχεδιαστικών προτύπων Εφαρµογή των 9 GRASP προτύπων

Κληρονομικότητα. Κληρονομικότητα (inheritance) είναι ο τρόπος µε τον οποίο μία τάξη μπορεί να κληρονομήσει ιδιότητες και συμπεριφορά από άλλες τάξεις.


Διαγράμματα UML στην Ανάλυση. Μέρος Β Διαγράμματα Κλάσεων Διαγράμματα Αντικειμένων

Αντικειμενοστρεφής Προγραμματισμός

1 ΕΙΣΑΓΩΓΗ. Πρωταρχικοί Τύποι

Οντοκεντρικός Προγραμματισμός

I (JAVA) Ονοματεπώνυμο: Α. Μ.: Δώστε τις απαντήσεις σας ΕΔΩ: Απαντήσεις στις σελίδες των ερωτήσεων ΔΕΝ θα ληφθούν υπ όψην.

Σύνθεση και Κληρονομικότητα

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Παράδειγμα χρήσης κληρονομικότητας

Οντοκεντρικός Προγραμματισμός

Ανάλυση Πληροφοριακών Συστημάτων. Εαρινό Εξάμηνο Lec08 09/04/2019 Διδάσκων: Γεώργιος Χρ. Μακρής

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κληρονομικότητα

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αναφορές Αντικείμενα ως ορίσματα

. Μεθοδολογία Προγραμματισμού. Μοτίβα σχεδίασης (Design Patterns) Νικόλαος Πεταλίδης. Εισαγωγή Εαρινό Εξάμηνο 2014

Τι χρειάζεται ένας φοιτητής για τη σωστή παρακολούθηση και συμμετοχή στο μαθημα;

Αντικειμενοστραφείς Γλώσσες Προγραμματισμού C++ / ROOT

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Σύνθεση αντικειμένων

ΠΛΗΡΟΦΟΡΙΚΗ Ι JAVA Τμήμα θεωρίας με Α.Μ. σε 3, 7, 8 & 9 6/12/07

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Σύνθεση αντικειμένων

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αντικείμενα ως ορίσματα Εισαγωγή στις αναφορές

Ανάλυση άσκησης. Employee. SalariedEmployee CommissionEmployee HourlyEmployee. BasePlusCommissionEmployee

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Υπάρχουσες κλάσεις και αντικείμενα στην Java Strings Wrapper Classes Δομές

Κλάσεις. Κατηγορίες Αντικειµένων. Κλάσεις. Φυσικά Αντικείµενα. Χώρος = Οµάδα Φυσικών Αντικειµένων. Πρόγραµµα = Οµάδα

(Απλή) Κληρονομικότητα

Διάλεξη 06: Συνδεδεμένες Λίστες & Εφαρμογές Στοιβών και Ουρών

14η ιάλεξη. Προχωρημένα θέματα σχεδίασης

ΑΣΦΑΛΕΙΑ ΔΕΔΟΜΕΝΩΝ ΣΤΗΝ ΚΟΙΝΩΝΙΑ ΤΗΣ ΠΛΗΡΟΦΟΡΙΑΣ (Μηχανισμοί Ελέγχου Προσπέλασης)

Πληροφοριακά Συστήματα Διοίκησης Ενότητα 1: Βασικές Αρχές Αντικειμενοστραφούς Σχεδίασης Συστημάτων και Εφαρμογών (1ο Μέρος)

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Σύνθεση αντικειμένων Παράδειγμα: Τμήμα πανεπιστημίου

Καρακασίδης Αλέξανδρος Καστίδου Γεωργία Παπαφώτη Μαρία Πέτσιος Κων/νος Στέφανος Σαλτέας Καλογεράς Παναγιώτης. Threads in Java ΝΗΜΑΤΑ ΣΤΗ JAVA

ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΕΦΗΣ ΑΝΑΛΥΣΗ ΥΛΟΠΟΙΗΣΗ ΣΤΟΙΧΕΙΩΝ ΑΝΑΛΥΣΗΣ UML ΜΕ JAVA. Ιωάννης Σταμέλος Βάιος Κολοφωτιάς Πληροφορική

Γενικά (για τις γραπτές εξετάσεις)

Διάλεξη 16-17: Πολυμορφισμός (Polymorphism) Διδάσκων: Παναγιώτης Ανδρέου

Προγραμματισμός Ι. Κλάσεις και Αντικείμενα. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Μοτίβα Σχεδίασης (Design Patterns)

Μέθοδοι. Υποσυστήµατα και πακέτα. Μοντέλα αντικειµενοστραφούς σχεδίασης. Αντικειµενοστραφής Σχεδίαση. Στα πρώτα στάδια της ανάλυσης

Καλές επιτυχίες παιδιά στα υπόλοιπα μαθήματά σας και καλές γιορτές!!!!

Transcript:

Πρότυπα Σχεδίασης Design Patterns 1

Bridge (Γέφυρα) Κατηγορία: Structural Σκοπός: Η αποσύνδεση μιας αφαίρεσης από την υλοποίησή της, ώστε να μπορούν να μεταβάλλονται ανεξάρτητα. Συνώνυμα: Handle/Body 2

Bridge (Γέφυρα) Όταν μία αφαίρεση μπορεί να έχει περισσότερες από μία υλοποιήσεις, ο συνήθης τρόπος οργάνωσης είναι με τη χρήση κληρονομικότητας. Με τον όρο αφαίρεση νοείται μία αφηρημένη κλάση που ορίζει μία διασύνδεση (ένα σύνολο υπογραφών), ενώ υλοποιήσεις είναι οι συγκεκριμένες παράγωγες κλάσεις οι οποίες υλοποιούν τις μεθόδους της αφηρημένης κλάσεις. Πρόβλημα: Αφαίρεση και υλοποιήσεις συνδέονται μόνιμα, καθιστώντας δύσκολη την επέκταση, τροποποίηση και επαναχρησιμοποίηση αφαιρέσεων και υλοποιήσεων ανεξάρτητα. 3

Bridge (Γέφυρα) Το πρότυπο "Γέφυρα" είναι σχετικά δύσκολο στην κατανόησή του Χρησιμοποιείται ωστόσο σε πληθώρα περιπτώσεων όπου εντοπίζονται: Μεταβολές στην αφαίρεση μιας έννοιας Μεταβολές στον τρόπο υλοποίησης της έννοιας αυτής Η Γέφυρα αντίκειται επίσης στη συνήθη τάση χειρισμού αντίστοιχων καταστάσεων μόνο με κληρονομικότητα. Ικανοποιεί όμως δύο από τους βασικούς κανόνες της αντικειμενοστραφούς κοινότητας: "Εντοπίστε αυτό που μεταβάλλεται και ενσωματώστε το", και "προτιμήστε σύνθεση αντικειμένων από κληρονομικότητα κλάσεων". 4

Bridge (Γέφυρα) Θεωρούμε μία εφαρμογή η οποία χειρίζεται τις πληρωμές τεχνικών υπαλλήλων (TechEmployees). Η πληρωμή των υπαλλήλων είναι δυνατόν να πραγματοποιείται είτε με βάση το μηνιαίο μισθό, είτε με βάση τον αριθμό ωρών εργασίας ανά μήνα και την αντίστοιχη αμοιβή ανά ώρα. Ο υπολογισμός του μισθού, κρατήσεων κλπ πραγματοποιείται από δύο ανεξάρτητα προγράμματα, που αντιστοιχούν στις κλάσεις Pay1 και Pay2. 5

Bridge (Γέφυρα) Η εφαρμογή θα πρέπει να είναι σε θέση να λειτουργήσει με υπάλληλο οποιασδήποτε κατηγορίας πληρωμής, αλλά δεν οφείλει να γνωρίζει εκ των προτέρων τον τρόπο πληρωμής κάθε υπαλλήλου. Οι υπάλληλοι θα σχετίζονται με συγκεκριμένο τρόπο πληρωμής κατά την υλοποίηση των αντικειμένων τους, και κατά συνέπεια είναι λογικό η εφαρμογή να διατηρεί έναν δείκτη προς μία αφηρημένη κλάση Τεχνικός Υπάλληλος από την οποία θα κληρονομούν οι δύο συγκεκριμένες κατηγορίες με βάση τον τρόπο πληρωμής. Η κάθε κατηγορία διατηρεί δείκτη προς την αντίστοιχη κλάση υπολογισμού του μισθού. 6

Bridge (Γέφυρα) Client TechEmployee +calcsalary() TechEmployee1 TechEmployee2 +calcsalary() +calcsalary() PayPerMonth PayPerHour +paytechempl() +paytechempl() 7

Bridge (Γέφυρα) Η τροποποίηση των απαιτήσεων είναι αναπόφευκτη: Ζητείται ο εμπλουτισμός της εφαρμογής, ώστε να μπορεί να χειρίζεται και την πληρωμή πωλητών (SalesEmployees), οι οποίοι είναι επίσης δυνατόν να πληρώνονται με οποιονδήποτε από τους δύο τρόπους. Η προφανής αντιμετώπιση του προβλήματος από έναν αναλυτή αντικειμενοστραφών συστημάτων είναι η χρήση κληρονομικότητας. Ορίζοντας μία επιπλέον αφηρημένη κλάση, τύπου Υπάλληλος, είναι δυνατόν να κληρονομούν οι δύο ειδικές κατηγορίες υπαλλήλων, ώστε η εφαρμογή να συνεχίσει να μπορεί να χειρίζεται οποιονδήποτε υπάλληλο. Η ανάλυση αυτή, οδηγεί στο διάγραμμα κλάσεων του σχήματος 8

Bridge (Γέφυρα) Client Employee +calcsalary() TechEmployee SalesEmployee +calcsalary() +calcsalary() TechEmployee1 TechEmployee2 SalesEmployee1 SalesEmployee2 +calcsalary() +calcsalary() +calcsalary() +calcsalary() PayPerMonth PayPerHour +paytechempl() +paysalesempl() +paytechempl() +paysalesempl() 9

Bridge (Γέφυρα) Πολυπλοκότητα του σχεδίου: Αν υπάρχει μεταβολή στην υλοποίηση, όπως για παράδειγμα αν προστεθεί ένας επιπλέον τρόπος πληρωμής (π.χ. ανά τεμάχιο), ο αριθμός των συγκεκριμένων κλάσεων που αναπαριστούν κατηγορίες υπαλλήλων/τρόπων πληρωμής, θα αυξηθεί σε έξι. Αν μεταβληθεί η αφαίρεση, όπως για παράδειγμα αν προστεθεί μία επιπλέον κατηγορία υπαλλήλου, ο αριθμός των κλάσεων επίσης θα αυξηθεί σημαντικά. Η εκρηκτική αυτή αύξηση του αριθμού των κλάσεων στο σύστημα, προκαλείται διότι η αφαίρεση (οι κατηγορίες των Υπαλλήλων) και οι υλοποιήσεις (οι διαφορετικοί τρόποι πληρωμών) έχουν υψηλή σύζευξη. Κάθε τύπος Υπαλλήλου πρέπει να γνωρίζει την κλάση που υπολογίζει την πληρωμή του. Ο στόχος του προτύπου σχεδίασης "Γέφυρα" είναι ο διαχωρισμός των μεταβολών στην αφαίρεση από τις μεταβολές στην υλοποίηση, ώστε ο αριθμός των κλάσεων να αυξάνει γραμμικά. 10

Bridge (Γέφυρα) Στρατηγική: εντοπισμός των εννοιών που μεταβάλλονται και ενσωμάτωσή τους επιλογή σύνθεσης στη θέση της κληρονομικότητας. Στη συγκεκριμένη εφαρμογή μεταβάλλονται οι έννοιες του Υπαλλήλου (Employee) και του Τρόπου Πληρωμής (Pay). Η ενσωμάτωση των εννοιών που μεταβάλλονται επιτυγχάνεται με τη χρήση αφηρημένων κλάσεων για κάθε έννοια. Οι διάφορες έννοιες πλέον αναπαριστώνται ως παράγωγες κλάσεις αυτών των αφηρημένων κλάσεων. 11

Bridge (Γέφυρα) Employee Pay +calcsalary() +paytechempl() +paysalesempl() TechEmployee SalesEmployee PayPerMonth PayPerHour +calcsalary() +calcsalary() +paytechempl() +paysalesempl() +paytechempl() +paysalesempl() Το ερώτημα που τίθεται είναι με ποιο τρόπο οι δύο αυτές ομάδες κλάσεων θα συσχετιστούν μεταξύ τους. Η κληρονομικότητα ωστόσο πρέπει να αποφευχθεί διότι η εισαγωγή ενός επιπλέον επιπέδου δημιουργεί τα προβλήματα που συζητήθηκαν προηγουμένως. Ακολουθώντας τον κανόνα που επιβάλλει να προτιμηθεί η σύνθεση, επιλέγεται η επιλογή μιας σχέσης περιεκτικότητας του τρόπου πληρωμής (Pay) στην έννοια του Υπαλλήλου (Employee). 12

Bridge (Γέφυρα) Employee Pay +calcsalary() +paytechempl() +paysalesempl() TechEmployee SalesEmployee PayPerMonth PayPerHour +calcsalary() Αφαίρεση Υπάλληλος +calcsalary() +paytechempl() +paysalesempl() Υλοποίηση Πληρωμής +paytechempl() +paysalesempl() 13

Bridge (Γέφυρα) Πλεονεκτήματα: Οι υλοποιήσεις δεν είναι μόνιμα συσχετισμένες με μία διασύνδεση. Η υλοποίηση μιας αφαίρεσης μπορεί να διαμορφώνεται ή και να τροποποιείται κατά το χρόνο εκτέλεσης. Στο παράδειγμα, ένα αντικείμενο τύπου TechEmployee μπορεί κατά την εκτέλεση του προγράμματος να συσχετιστεί με τον τρόπο πληρωμής ανά ώρα και στη συνέχεια να τροποποιηθεί ο τρόπος πληρωμής του σε πληρωμή ανά μήνα. Οποιαδήποτε αλλαγή στις υλοποιήσεις, δεν απαιτεί μεταγλώττιση των κλάσεων στην ιεραρχία της αφαίρεσης ή των προγραμμάτων που τις χρησιμοποιούν. Οποιαδήποτε από τις δύο ιεραρχίες κλάσεων (Αφαίρεση και Υλοποίηση) μπορεί να επεκταθεί (προσθέτοντας περισσότερα επίπεδα) με τρόπο ανεξάρτητο. 14

Bridge (Γέφυρα) Πελάτης Αφαίρεση υλοπ Υλοποίηση +Λειτουργία() υλοπ -> ΥλοπΛειτουργία(); +ΥλοπΛειτουργία() ΕκλεπτυσμένηΑφαίρεση ΣυγκεκριμένηΥλοποίησηΑ +ΥλοπΛειτουργία() ΣυγκεκριμένηΥλοποίησηΒ +ΥλοπΛειτουργία() 15

Singleton (Μοναδιαίο) Κατηγορία: Creational Σκοπός: Η εξασφάλιση ότι μία κλάση θα έχει μόνο ένα στιγμιότυπο και παρέχει ένα καθολικό σημείο πρόσβασης σε αυτό. Συνώνυμα: - 16

Singleton (Μοναδιαίο) Κλάσεις και στιγμιότυπα: Σχέση ένα-προς-πολλά. Τα αντικείμενα δημιουργούνται δεσμεύοντας χώρο στη μνήμη όποτε κρίνεται σκόπιμο και διαγράφονται από τη μνήμη ότι τερματιστεί η χρήση τους. Ορισμένες φορές, απαιτείται η ύπαρξη κλάσεων από τις οποίες παράγεται ένα μόνο αντικείμενο. Το αντικείμενο αυτό συνήθως δημιουργείται κατά την έναρξη της εφαρμογής και διαγράφεται με το πέρας της. Ο ρόλος του μοναδικού αυτού αντικειμένου είναι η διαχείριση των υπολοίπων αντικειμένων της εφαρμογής και για το λόγο αυτό, αποτελεί λογικό σφάλμα να δημιουργηθούν περισσότερα του ενός τέτοια αντικείμενα-διαχειριστές (managers ή controllers). 17

Singleton (Μοναδιαίο) Το πρότυπο σχεδίασης "Μοναδιαίο", εξασφαλίζει τη δημιουργία ενός και μόνο αντικειμένου, περιλαμβάνοντας μία ειδική μέθοδο κατασκευής στιγμιοτύπων: Όταν καλείται αυτή η μέθοδος, ελέγχει αν κάποιο αντικείμενο έχει ήδη δημιουργηθεί. Αν ναι, η μέθοδος επιστρέφει απλώς έναν δείκτη προς το υπάρχον αντικείμενο. Αν όχι, η μέθοδος δημιουργεί ένα νέο αντικείμενο και επιστρέφει δείκτη προς αυτό. Για να εξασφαλισθεί ότι αυτός είναι ο μοναδικός τρόπος δημιουργίας αντικειμένων από αυτή την κλάση, ο κατασκευαστής της κλάσης δηλώνεται ως προστατευμένος (protected) ή ιδιωτικός (private). Με τον τρόπο αυτό, δεν είναι δυνατόν να δημιουργηθεί ένα αντικείμενο, χωρίς να κληθεί η παραπάνω ειδική μέθοδος. 18

Singleton (Μοναδιαίο) Παράδειγμα: Μοντέλο μιας CPU. Πολλοί καταχωρητές γενικής χρήσης, μόνο (Accumulator). ένας συσσωρευτής Η εφαρμογή πρέπει να εξασφαλίσει ότι δεν θα δημιουργηθούν πέραν του ενός τέτοιοι συσσωρευτές και ότι οι λειτουργίες του καταχωρητή θα είναι καθολικά προσπελάσιμες. 19

Singleton (Μοναδιαίο) Εφαρμογή του προτύπου "Μοναδιαίο" και ορίζοντας στην κλάση Accumulator μία στατική λειτουργία getinstance η οποία δημιουργεί ένα αντικείμενο μόνο όταν αυτό δεν υφίσταται. Η λειτουργία είναι δηλωμένη στατική, έτσι ώστε να μπορεί να κληθεί και πριν από την κατασκευή του μοναδικού αντικειμένου. Η κλάση περιλαμβάνει ένα στατικό μέλος instance, δείκτη προς το μοναδικό αντικείμενο (όσο αυτό δεν υφίσταται, η τιμή του δείκτη είναι NULL). Η λειτουργία getinstance σε περίπτωση που η τιμή του δείκτη instance είναι NULL δημιουργεί ένα αντικείμενο της κλάσης.. Σε περίπτωση που ο δείκτης έχει ήδη μία τιμή, η λειτουργία απλώς επιστρέφει την τιμή του. 20

Singleton (Μοναδιαίο) class Accumulator { public: static Accumulator* getinstance(); protected: Accumulator(); private: static Accumulator* instance; }; Accumulator* Accumulator::instance = NULL; Accumulator* Accumulator::getInstance() { if(instance == NULL) instance = new Accumulator; } return instance; 21

Singleton (Μοναδιαίο) Lazy Initialization: Η τιμή που επιστρέφει η μέθοδος, δεν δημιουργείται μέχρι την πρώτη κλήση της. Αν επομένως ένα μοναδιαίο αντικείμενο δεν χρησιμοποιηθεί, δεν δημιουργείται. Στο παρακάτω πρόγραμμα, οι δύο εντολές printf επιστρέφουν την ίδια διεύθυνση για τους δείκτες A και A1. int main() { Accumulator* A; A = Accumulator::getInstance(); Accumulator* A1; A1 = Accumulator::getInstance(); printf("a address: %p\n", A); printf("a1 address: %p\n", A1); return 0; } 22

Singleton (Μοναδιαίο) Aπλότητα: οποιαδήποτε κλάση να μετατραπεί σε μοναδιαία. Πλεονέκτημα: σε περίπτωση δημιουργίας παράγωγων κλάσεων από μία μοναδιαία κλάση, κάθε απόγονος μπορεί να είναι επίσης μοναδιαία κλάση αν προστεθούν και σε αυτές η στατική ιδιότητα και μέθοδος. Για παράδειγμα, αν υπάρχουν ειδικές κατηγορίες συσσωρευτών από τις οποίες μπορεί να επιλέξει ο σχεδιαστής, κάθε κατηγορία μπορεί να κληρονομεί από την κλάση Accumulator. Καθώς η ιδιότητα instance είναι δείκτης προς αντικείμενα τύπου Accumulator, η μέθοδος getinstance μπορεί να αναθέσει στην instance την τιμή ενός δείκτη προς οποιαδήποτε παράγωγη κλάση. 23

Singleton (Μοναδιαίο) Μοναδιαίο -στιγμιότυπο -δεδομένο +υλοποίηση_στιγμιοτύπου() +λειτουργία() +λήψηδεδομένου() return στιγμιότυπο 24

Visitor (Επισκέπτης) Υλοποιεί τη λεγόμενη "διπλή αποστολή" (double dispatch ή dual dispatch). Τα μηνύματα στον OOP κατά κανόνα επιδεικνύουν συμπεριφορά που αντιστοιχεί στην "απλή αποστολή": -η λειτουργία που εκτελείται εξαρτάται: - από το όνομα της αίτησης - τον τύπο του (μοναδικού) αποδέκτη Στη "διπλή αποστολή" η λειτουργία που εκτελείται εξαρτάται: - από το όνομα της αίτησης και - τον τύπο δύο αποδεκτών (στο συγκεκριμένο πρότυπο από τον τύπο του "Επισκέπτη" και τον τύπο του στοιχείου που 25 επισκέπτεται).

Visitor (Επισκέπτης) Παράδειγμα: εφαρμογή η οποία διαχειρίζεται το εισόδημα (Income) και τις μέρες αδείας (Vacation Days) των υπαλλήλων μιας εταιρείας Employee -name -income -vacationdays +getvacationdays() Technician +getincome() AdministrativeEmployee -bonus +getincome() donwload αρχικό κώδικα από macedonia.uom.gr 26

Visitor (Επισκέπτης) Νέες απαιτήσεις: Υποθέτουμε ότι η εταιρεία εφαρμόζει μία πολιτική τροποποίησης των μισθών και αδειών σε τακτά χρονικά διαστήματα. Η τροποποίηση των κλάσεων είναι υπαρκτή δυνατότητα, αλλά δεν είναι ρεαλιστική. Φιλοσοφία: προσθήκη λειτουργικότητας χωρίς την αλλαγή του κώδικα υπαρχόντων κλάσεων. Υλοποίηση: Δημιουργία μίας ιεραρχίας κλάσεων Επισκέπτη (Visitor class hierarchy) η οποία ορίζει αμιγώς υπερβατές μεθόδους visit() στην αφηρημένη κλάση βάσης. Κάθε μέθοδος visit() λαμβάνει μία μοναδική παράμετρο έναν δείκτη ή αναφορά προς μία κλάση της αρχικής ιεραρχίας. 27

Visitor (Επισκέπτης) Σχεδίαση: 1ο Στάδιο: Κάθε νέα λειτουργία μοντελοποιείται ως παράγωγος κλάσης της ιεραρχίας των Επισκεπτών. Οι αφηρημένες μέθοδοι visit() υλοποιούν την επιθυμητή λειτουργικότητα για τη συγκεκριμένη κλάση που δέχονται ως παράμετρο. Πώς λαμβάνει κάθε κλάση "Επισκέπτης" το δείκτη ή την αναφορά προς το στοιχείο που καλείται να εμπλουτίσει με νέα λειτουργικότητα? 2ο Στάδιο: προσθήκη αφηρημένης μεθόδου accept() στη βασική κλάση της πρωτότυπης ιεραρχίας. Η accept() λαμβάνει έναν δείκτη προς την αφηρημένη κλάση βάσης της ιεραρχίας των Επισκεπτών. Κάθε στοιχείο της πρωτότυπης ιεραρχίας, υλοποιεί την accept() καλώντας τη μέθοδο visit() του στιγμιοτύπου των Επισκεπτών που 28 της δόθηκε ως παράμετρος, περνώντας τον "this" pointer.

Visitor (Επισκέπτης) Εφαρμογή: όταν ο πελάτης χρειάζεται να προσθέσει μία λειτουργία: Βήμα 1ο: δημιουργεί ένα στιγμιότυπο του αντικειμένου Επισκέπτη που αφορά στη συγκεκριμένη λειτουργικότητα. Βήμα 2ο: καλεί τη μέθοδο accept() σε κάθε στοιχείο της πρωτότυπης ιεραρχίας που επιθυμεί να εμπλουτίσει περνώντας ως όρισμα το αντικείμενο Επισκέπτη. Η μέθοδος accept() μέσω της "διπλής αποστολής" καθοδηγεί τη ροή του ελέγχου στην κατάλληλη κλάση Visitor και στη συνέχεια στην εκτέλεση της λειτουργικότητας στην επιθυμητή αρχική κλάση. 29

Visitor (Επισκέπτης) Διάγραμμα UML: Employee -name -income -vacationdays +getvacationdays() +accept(visitor)() Visitor +visit(technician)() +visit(administrativeemployee)() Technician AdministrativeEmployee IncomeVisitor VacationDaysVisitor -bonus +getincome() +getincome() public void accept(visitor v) { v.visit(this); } 30

Visitor (Επισκέπτης) Παρατήρηση: Η προσθήκη νέων μεθόδων είναι πλέον σχετικά εύκολη αρκεί η προσθήκη μιας νέας υποκλάσης στην ιεραρχία των Επισκεπτών. Ωστόσο, αν οι κλάσεις στην αρχική ιεραρχία δεν είναι σταθερές, τότε ο συγχρονισμός μεταξύ της ιεραρχίας των Επισκεπτών και της ιεραρχίας των αρχικών κλάσεων απαιτεί μεγάλη προσπάθεια, που ίσως να μη δικαιολογεί τη χρήση του προτύπου. 31

Visitor (Επισκέπτης) Γενική Δομή - Εφαρμογή: Χρησιμοποιείστε το πρότυπο σχεδίασης "Επισκέπτης" : όταν θέλετε να προσθέσετε λειτουργίες στα αντικείμενα μιας ιεραρχίας αντικειμένων χωρίς να "μολύνετε" τις κλάσεις τους με αυτές τις λειτουργίες. Το πρότυπο "Επισκέπτης" σας επιτρέπει να διατηρείτε σχετιζόμενες λειτουργίες σε ένα μέρος ορίζοντας αυτές σε μία ξεχωριστή κλάση. Διάγραμμα: 32

Visitor (Επισκέπτης) Επισκέπτης Πελάτης +επίσκεψη(συγκεκριμένοστοιχείοα)() +επίσκεψη(συγκεκριμένοστοιχείοβ)() ΣυγκεκριμένοςΕπισκέπτης1 ΣυγκεκριμένοςΕπισκέπτης2 +επίσκεψη(συγκεκριμένοστοιχείοα)() +επίσκεψη(συγκεκριμένοστοιχείοβ)() +επίσκεψη(συγκεκριμένοστοιχείοα)() +επίσκεψη(συγκεκριμένοστοιχείοβ)() Δομή Δεδομένων Στοιχείο +αποδοχή(επισκέπτης)() ΣυγκεκριμένοΣτοιχείοΑ ΣυγκεκριμένοΣτοιχείοΒ +αποδοχή(επισκέπτης v)() +λειτουργίαα() +αποδοχή(επισκέπτης v)() +λειτουργίαβ() v->επίσκεψη(this) v->επίσκεψη(this) 33

abstract class Employee { public Employee(String text, double amount, int days) { name = text; income = amount; vacationdays = days; } public void setname(string text) { name = text; } public void setincome(double amount) { income = amount; } public void setvacationdays(int days) { vacationdays = days; } public String getname() { return name; } public int getvacationdays() { return vacationdays; } public abstract void accept(visitor visitor); } private String name; protected double income; private int vacationdays; 34

class Technician extends Employee { } public Technician(String text, double amount, int days) { super(text, amount, days); } public double getincome() { return income; } public void accept(visitor visitor) {visitor.visit(this);} 35

class AdministrativeEmployee extends Employee { public AdministrativeEmployee(String text, double amount, int days, int extra) { super(text, amount, days); bonus = extra; } public void setbonus(double amount) { bonus = amount; } public double getbonus() { return bonus; } public double getincome() { return income; } public void accept(visitor visitor) {visitor.visit(this);} } private double bonus; 36

interface Visitor { } public void visit(technician employee); public void visit(administrativeemployee employee); class IncomeVisitor implements Visitor { public void visit(technician employee) { //Technicians get an increase 10% of their income employee.setincome(employee.getincome() * 1.10); } } public void visit(administrativeemployee employee) { //Administrative Employees get an increase 20% of their bonus employee.setbonus(employee.getbonus() * 1.20); } 37

class VacationDaysVisitor implements Visitor { public void visit(technician employee) { //Technicians get an increase of 3 days employee.setvacationdays(employee.getvacationdays() + 3); } } public void visit(administrativeemployee employee) { //Administrative Employees get an increase of 2 days employee.setvacationdays(employee.getvacationdays() + 2); } 38

public class VisitorTestFull { public static void main(string[] args) { Technician E1 = new Technician("Fred", 2000, 23); AdministrativeEmployee E2 = new AdministrativeEmployee("John", 3000, 25, 200); System.out.println(E1.getName() + ", Total Income: " + E1.getIncome() + ", Vacation Days: " + E1.getVacationDays() ); System.out.println(E2.getName() + ", Total Income: " + (E2.getIncome()+E2.getBonus()) + ", Vacation Days: " + E2.getVacationDays() ); IncomeVisitor v1 = new IncomeVisitor(); VacationDaysVisitor v2 = new VacationDaysVisitor(); E1.accept(v1); E2.accept(v1); E1.accept(v2); E2.accept(v2); System.out.println("After visits have been performed..."); System.out.println(E1.getName() + ", Total Income: " + E1.getIncome() + ", Vacation Days: " + E1.getVacationDays() ); System.out.println(E2.getName() + ", Total Income: " + (E2.getIncome()+E2.getBonus()) + ", Vacation Days: " + E2.getVacationDays() ); } } 39

Observer (Παρατηρητής) Κατηγορία: Behavioral Σκοπός: Ο ορισμός μιας σχέσης εξάρτησης ένα-προς-πολλά μεταξύ αντικειμένων έτσι ώστε όταν μεταβάλλεται η κατάσταση ενός αντικειμένου, όλα τα εξαρτώμενα αντικείμενα να ενημερώνονται και να τροποποιούνται αυτόματα. Συνώνυμα: Publish - Subscribe 40

Observer (Παρατηρητής) Στόχος της αντικειμενοστραφούς σχεδίασης είναι η δημιουργία ενός συνόλου αλληλεπιδρώντων αντικειμένων. Συχνό πρόβλημα: η αναγκαιότητα συνεργασίας μεταξύ κλάσεων, οδηγεί σε υψηλή σύζευξη. Ορισμένα από τα πρότυπα, με χαρακτηριστικότερο το πρότυπο "Παρατηρητής", επιδιώκουν να μειώσουν τη σύζευξη μεταξύ των αντικειμένων, παρέχοντας αυξημένη δυνατότητα επαναχρησιμοποίησης και τροποποίησης του συστήματος. 41

Observer (Παρατηρητής) Το συγκεκριμένο πρότυπο, επιτρέπει την αυτόματη ειδοποίηση και ενημέρωση ενός συνόλου αντικειμένων τα οποία "αναμένουν" ένα γεγονός, που εκδηλώνεται ως αλλαγή στην κατάσταση ενός αντικειμένου. Ο στόχος είναι η από-σύζευξη των παρατηρητών από το παρακολουθούμενο αντικείμενο, έτσι ώστε κάθε φορά που προστίθεται ένας νέος παρατηρητής (με διαφορετική διασύνδεση ενδεχομένως), να μην απαιτούνται αλλαγές στο παρακολουθούμενο αντικείμενο Το συγκεκριμένο πρότυπο είναι από τα πλέον ευρέως χρησιμοποιούμενα και υλοποιείται με σχετική ευκολία σε διάφορες γλώσσες προγραμματισμού. Το πρότυπο "Παρατηρητής" εφαρμόζεται για χρόνια στην γνωστή αρχιτεκτονική Μοντέλου-Όψεως-Έλεγκτή (Model-View-Controller) 42

Observer (Παρατηρητής) Η εφαρμογή του προτύπου προϋποθέτει τον εντοπισμό των εξής δύο τμημάτων: ενός υποκειμένου και του παρατηρητή. Μεταξύ των δύο υφίσταται μία συσχέτιση ένα-προς-πολλά Το υποκείμενο διατηρεί το μοντέλο των δεδομένων και η λειτουργικότητα που αφορά στην παρατήρηση των δεδομένων κατανέμεται σε διακριτά αντικείμενα παρατηρητές. Οι παρατηρητές αυτό-καταχωρούνται στο υποκείμενο κατά τη δημιουργία. Οποτεδήποτε το υποκείμενο αλλάζει, "ανακοινώνει" προς όλους τους καταχωρημένους παρατηρητές το γεγονός της αλλαγής. Κάθε παρατηρητής ερωτά το υποκείμενο για το υποσύνολο της κατάστασης του υποκειμένου που το ενδιαφέρει Στο ανωτέρω πρωτόκολλο επικοινωνίας η πληροφορία "αντλείται" αντί να 43 αποστέλλεται στους παρατηρητές,

Observer (Παρατηρητής) Παράδειγμα: Κλάση Timer που υλοποιεί ένα χρονόμετρο class Timer extends Subject { private int state; } public int getstate() { return state; } public void setstate( int in ) { state = in; Notify(); } 44

Observer (Παρατηρητής) Αρχή Αντιστροφής των Εξαρτήσεων: Οι παρατηρητές δεν θα πρέπει να "βλέπουν" μία συγκεκριμένη κλάση, για αυτό και η Timer κληρονομεί μία αφηρημένη κλάση βάσης class Subject { private ArrayList observers = new ArrayList(); private int totalobs = 0; public void attach( Observer o ) { observers.add(o); } //καταχώρηση παρατηρητή public void detach( Observer o) { observers.remove( o ); } } public void Notify() { for (int i=0; i < observers.size(); i++) ((Observer)observers.get(i)).update(); //ανακοίνωση αλλαγών στους παρατηρητές } 45

Observer (Παρατηρητής) Η τιμή του χρονομέτρου εμφανίζεται στην οθόνη από διάφορους παρατηρητές Όλοι οι παρατηρητές πρέπει να έχουν την ίδια διασύνδεση. Λύση: Κληρονομούν μία αφηρημένη βασική κλάση (Observer) abstract class Observer { public abstract void update(); } 46

Observer (Παρατηρητής) Οι παρατηρητές καταχωρούν τον εαυτό τους καλώντας την attach του υποκειμένου ( public void attach (Observer o) ) Αν ο παρατηρητής χρειάζεται περισσότερη πληροφορία, την "αντλεί" από το υποκείμενο class HexObserver extends Observer { private Timer subj; } public HexObserver( Timer s ) { subj = s; subj.attach( this ); //Οι παρατηρητές καταχωρούν τον εαυτό τους } public void update() { System.out.print(" "+Integer.toHexString(subj.getState()) ); } //Οι παρατηρητές αντλούν πληροφορία 47

Observer (Παρατηρητής) Subject observers Observer +attach(observer)() +detach(observer)() +Notify() for all o in observers { o -> Update() } +update() Timer -state : int subj HexObserver OctObserver BinObserver +getstate() +setstate() +update() +update() subj +update() subj return state; 48

Observer (Παρατηρητής) H εφαρμογή του προτύπου έχει νόημα μόνο όταν η λίστα των παρατηρητών αλλάζει δυναμικά Ειδάλλως (αν για παράδειγμα το υποκείμενο επικοινωνεί πάντοτε με ένα συγκεκριμένο παρατηρητή) η σύζευξη μεταξύ τους κωδικοποιείται ως απλή συσχέτιση 49

Στρατηγική (Strategy) Ορίζει μια οικογένεια αλγορίθμων, τους ενσωματώνει και επιτρέπει την εναλλαγή μεταξύ αυτών. Το χρησιμοποιούμε όταν θέλουμε να υλοποιήσουμε έναν κοινό γενικό αλγόριθμο (π.χ. ταξινόμηση) αλλά και πολλές διαφοροποιήσεις του (π.χ. φυσαλίδας, εισαγωγής κ.τ.λ.) 50

Στρατηγική (Strategy) Έστω ότι θέλουμε να δημιουργήσουμε ένα πρόγραμμα το οποίο να βρίσκει την μέγιστη και την ελάχιστη τιμή σε έναν πίνακα Επιπλέον, επιθυμούμε για την υλοποίηση του προγράμματος να εκτελείτε αρχικά μια ταξινόμηση του πίνακα. Τέλος, επιθυμητό είναι ο χρήστης του προγράμματος να επιλέγει τον αλγόριθμο ταξινόμησης κατά τη διάρκεια της εκτέλεσης 51

Στρατηγική (Strategy) 52

Σχεδιάστε το διάγραμμα κλάσεων για ένα θερμόμετρο το οποίο καταγράφει τη θερμοκρασία του περιβάλλοντος και στη συνέχεια ανάλογα με αυτή μπορεί να αυξομειώνει την ένταση του καλοριφέρ και να αλλάζει τις πληροφορίες (ώρα, βαθμοί C) που απεικονίζονται σε μια οθόνη 53

54

Θεωρούμε μία εφαρμογή η οποία απεικονίζει τρισδιάστατες σκηνές Κάθε αντικείμενο στην σκηνή μπορεί να χρωματιστεί με δύο τρόπους: είτε με βάση κάποια φωτογραφία, είτε με βάση ένα συγκεκριμένο χρώμα. Ο χρωματισμός των αντικειμένων πραγματοποιείται από δύο ανεξάρτητα προγράμματα, που αντιστοιχούν στις κλάσεις Texture και Material. 55

Scene e:object * [100 0..1 Object style_type Style +displayall:void +colormodel:float +colorprimitive:float +colormesh:float Primitive Mesh Texture Material Wire colormodel:floa colormodel:floa +colorprimitive:floa +colormesh:float +colorprimitive:floa +colormesh:float +colorprimitive:floa +colormesh:float 56

Περιγραφή του Model- Controller- View framework 57

58