Sign in | Join | Help
Καλωσήλθατε στο StudentGuru!

[Μαθαίνοντας Design Patterns] Factory

Συνεχίζοντας λοιπόν αυτή τη μικρή αναζήτηση γύρω από τα Design Patterns, σήμερα θα μιλήσουμε για το Factory. Πριν αναφέρω τα χαρακτηριστικά του pattern, ακολουθώντας τον τρόπο που ξεκίνησα το προηγούμενο post μου, θα ήθελα να πω τα εξής:

Έρχεται μια άλλη φάση στην ζωή του προγραμματιστή :P , που έχοντας αποφασίσει ότι θα κάνει το βήμα να μάθει να σχεδιάζει σωστά τον κώδικά του, ψάχνει να βρει πηγές που θα του δώσουν αυτό που θέλει να μάθει με τον καλύτερο και πιο κατανοητό τρόπο. Έτσι λοιπόν έκανα και εγώ...

Αναζήτησα το Design Patterns: Elements of Reusable Object-Oriented Software. Ένα παλιό βιβλίο (94), μία έκδοση έχει βγάλει, όλοι το θεωρούν την βίβλο των design patterns. Το πήρα και εγώ με αισιοδοξία για το μέλλον. Όσο όμως προσεκτικά και αν το διάβαζα δεν μπορούσα να κάνω κτήμα μου κάθε τι που έλεγε εκεί μέσα. Ήταν απλά αδύνατο, οι πληροφορίες ήταν τόσες πολλές, οι λεπτομέριες χαοτικές και η θεωρία τόσο πλήρης (πράγματα που όντως, κάνουν ένα βιβλίο, θρησκεία) που μόνο για να έχεις μια πρώτη επαφή με Design Patterns δεν ήταν...όσο και αν είχα την ελπίδα ότι θα τα καταφέρω εύκολα και γρήγορα, τουλάχιστον σε θεωρητικό επίπεδο, τόσο μπερδευόμουν όχι από θέμα ποιότητας (που ήταν άριστη), αλλά περιεκτικότητας πληροφορίας. Ένιωθα όπως τότε που είχα πάρει το βιβλίο των KnR για να μάθω C. Δεύτερη φορά στην ζωή μου λοιπόν. Και για να μην βρεθείτε σε παρόμοια κατάσταση θα το πω φωναχτά.

ΔΕΝ ΠΑΙΡΝΟΥΜΕ CORE REFERENCE MANUAL ΣΤΗΝ ΠΡΩΤΗ ΜΑΣ ΕΠΑΦΗ ΜΕ ΚΑΠΟΙΟ ΘΕΜΑ

Αυτή η φάση του προγραμματιστή λοιπόν, τελειώνει όταν βρούμε ένα βιβλίο απλό, κατανοητό και ταυτόχρονα να κρατάει υψηλό το επίπεδο της ποιότητας στις παρεχόμενες πληροφορίες.  Ένα τέτοιο βιβλίο είναι αυτό που μου πρότεινε ο φίλος Νίκος Παλλαδινός πρόσφατα και θα ήθελα να το μοιραστώ και με εσάς, μιας και το βρήκα τρομακτικά ενδιαφέρον (σε σημείο να απειλήσει λοιπές υποχρεώσεις μου) και πολύ έξυπνα γραμμένο. Και ο τίτλος αυτού Head First Design Patterns με κώδικα σε Java και με ένα εξώφυλλο που έχω ιδιαίτερη αδυναμία. Heheheh. Ακολουθώντας ένα μείγμα εμπειριών απο διάφορα βιβλία συνεχίζω να δίνω μια μικρή περιγραφή στα patterns για να συζητάμε κάθε φορά και να μαθαίνουμε μέσα από την συζήτηση.

 

Design Pattern 2#: Factory

Με το Factory pattern μπορούμε να δημιουργήσουμε μία διεπαφή η οποία θα μας επιστρέφει το νέο αντικείμενο που θέλουμε αλλά το είδους του αντικειμένου που θα επιστραφεί θα καθορίζεται στις υποκλάσεις. Αρκετά με την θεωρία. Μία πρόταση φτάνει. Ας πάμε κατευθείαν στο παράδειγμα για να δούμε πώς λειτουργεί το Factory pattern και που χρησιμοποιείται.

Το αγαπημένο μου θέμα. Πείτε ότι θέλουμε να φτιάξουμε ένα κατάστημα που να φτιάχνει σουβλάκια (no comments pls...show some respect στο τρόφιμο :P:P..hehe). Θέλω μία τέτοια μέθοδο δηλαδη

Souvlaki orderSouvlaki()
{
Souvlaki souvlaki = new Souvlaki();

souvlaki.etoimase();
souvlaki.tilikse();
souvlaki.paketarise();

return souvlaki;
}

Έστω λοιπόν ότι θέλω να προσθέσω κώδικα που να ελέγχει τι τύπο σουβλάκι θέλω να φτιάξω με βάση την περιοχή (τοπική παραλλαγή), θα έχω κάτι σαν αυτό:

Souvlaki orderSouvlaki(String perioxi)
{
Souvlaki souvlaki;

if (perioxi.Equals("notia_ellada"))
souvlaki = new KanonikoSouvlaki();
else if (perioxi.Equals("voreia_ellada"))
souvlaki = new VoreiasElladasSouvlaki();
else if (perioxi.Equals("kipriako"))
souvlaki = new KipriakiPitaSouvlaki();

souvlaki.etoimase();
souvlaki.tilikse();
souvlaki.paketarise();

return souvlaki;
}

Αν το κατάστημα δεν πουλάει πολύ σουβλάκια τύπου βόρειας ελλάδας, για να μην έχει απώλεια κέρδους θα πρέπει να σταματήσει την παρασκευή τους. Αν βλέπει ότι του ζητάνε σουβλάκι τύπου Ιωαννίνων κάτι θα έπρεπε να κάνει, οπότε:

Souvlaki orderSouvlaki(String perioxi)
{
Souvlaki souvlaki;

if (perioxi.Equals("notia_ellada"))
souvlaki = new KanonikoSouvlaki();
else if (perioxi.Equals("voreia_ellada"))
souvlaki = new VoreiasElladasSouvlaki();
else if (perioxi.Equals("kipriako"))
souvlaki = new KipriakiPitaSouvlaki();
else if (perioxi.Equals("ioannina"))
souvlaki = new GianniotikoSouvlaki();
souvlaki.etoimase();
souvlaki.tilikse();
souvlaki.paketarise();

return souvlaki;
}

Είναι προφανές ότι όταν θέλουμε να ρυθμίσουμε ποια κλάση θα αρχικοποιείται, υπάρχει σοβαρό πρόβλημα. Ο κώδικάς μας δεν είναι καθόλου modular. Έχουμε ένα στοιχείο όμως!!!! Ξέρουμε τώρα τι πρέπει να κάνουμε encapsulate!!! Καταρχάς φτιάχνουμε μια καινούρια μέθοδο αφαιρώτας το παραπάνω κομμάτι βάζοντας το σε μία μέθοδο που αναλαμβάνει αυτό ακριβώς το σημείο. Και έχουμε όνομα να της δώσουμε...SouvlakiFactory.

public class SouvlakiFactory
{
public Souvlaki createSouvlaki(String perioxi)
{
Souvlaki souvlaki;

if (perioxi.Equals("notia_ellada"))
souvlaki = new KanonikoSouvlaki();
else if (perioxi.Equals("voreia_ellada"))
souvlaki = new VoreiasElladasSouvlaki();
else if (perioxi.Equals("kipriako"))
souvlaki = new KipriakiPitaSouvlaki();
else if (perioxi.Equals("ioannina"))
souvlaki = new GianniotikoSouvlaki();

return souvlaki;
}

}

Μα τι κάναμε τώρα; Πήραμε το πρόβλημα και το μεταθέσαμε. Άλλαξε κάτι; Ναι! Άλλαξε κάτι πολύ σημαντικό. Το SouvlakiFactory μπορεί να έχει πολλούς clients και όχι μόνο την orderSouvlaki. Μπορεί να υπάρχει άλλη κλάση που να υπολογίζει την τιμή, ή να κανονίζει την παράδοση εφόσον υπάρχει διανομή κατοίκων. Έτσι, τώρα έχουμε ένα σημείο να κάνουμε αλλαγές. Ορίστε πως έχει τώρα ο κώδικάς μας.

SouvlakiFactory factory;

public Souvlantzidiko(SouvlakiFactory factory)
{
this.factory = factory;
}
Souvlaki orderSouvlaki(String perioxi)
{
Souvlaki souvlaki;
souvlaki = factory.createSouvlaki(perioxi);
souvlaki.etoimase();
souvlaki.tilikse();
souvlaki.paketarise();

return souvlaki;
}

Έστω τώρα ότι το κατάστημά μας επεκτείνεται σε όλη την Ελλάδα και ο κώδικας είναι παντού ο ίδιος. Παρόλα αυτά, όταν θα πάμε στην Σπάρτη, υπάρχει ένας ειδικός τύπος για Σουβλάκι Νότιας Ελλάδας(σπεσιαλ σαλτσα) που αρέσει στους ντόπιους. Δεν θα έπρεπε να έχω λοιπόν ένα ειδικό factory όπως το παρακάτω;

SpartiFactory spFactory = new SpartiFactory();
Souvlantzidiko spartiSouvlantzidiko = new Souvlantzidiko(spFactory);
spartiSouvlantzidiko.orderSouvlaki("notia_ellada");

Το πρόβλημα εδώ όμως είναι ότι δεν έχουμε τον έλεγχο το ποιος θα κάνει create τι. Πχ. κάποιος κάνει την δική επιχείρηση χρησιμοποιώντας το δικό σας factory. Χρειαζόμαστε μία ακόμα πινελιά για να έχουμε το Factory μας δεμένο με το κάθε κατάστημα. Παρατηρείστε το σχόλιο στην abstract κλάση

public abstract class Souvlantzidiko
{
public Souvlantzidiko(SouvlakiFactory factory)
{
}

Souvlaki orderSouvlaki(String perioxi)
{
Souvlaki souvlaki;
souvlaki = createSouvlaki(perioxi);
souvlaki.etoimase();
souvlaki.tilikse();
souvlaki.paketarise();

return souvlaki;
}
//To factory object υπάρχει εδώ. Αυτό ακριβώς το σημείο
//είναι εκείνο στο οποίο αποφασίζει η κάθε υποκλάση την υλοποίηση που θέλει.
protected abstract Souvlaki createSouvlaki(String perioxi);
}

Το factory pattern όπως το αναλύσαμε εδώ μπορεί να χρησιμοποιηθεί σε πάρα πολλές καταστάσεις και αν το καταλάβουμε καλά, θα μας λύσει τα χέρια σε πολλά σημεία. Στο .NET υπάρχει υλοποιημένο σε πολλές λειτουργίες της βιβλιοθήκης εξυπηρετώντας κάθε φορά αυτήν την λειτουργικότητα. Για παράδειγμα, για να διαβάσετε/στείλετε δεδομένα στο δίκτυο με βάση ένα uri μπορείτε να χρησιμοποιήσετε την System.Net.WebRequest. Αν ξέρετε λίγο από system programming κάθε πρωτόκολλο ακολουθεί αυστηρά τις δικές του συμβάσεις επικοινωνίας, τόσο στην δημιουργία sockets όσο και στα μηνύματα που ανταλάσσονται κλπ. Η WebRequest.Create δημιουργεί ένα αρμόδιο αντικείμενο με βάση το URI που θα του δώσουμε επιστρέφοντας μας το κατάλληλο instance που θα μας επιτρέψει την επικοινωνία. Το uri μπορεί να είναι ένα από τα τρία (default) "http://", "https://", and "file://".

Enjoy, stay tuned!!!

Share/Bookmark
Published Δευτέρα, 11 Φεβρουαρίου 2008 9:06 μμ by Aggelos Mpimpoudis

Comments

# [Μαθαίνοντας Design Patterns]Factory

Στο δεύτερο post της σειράς "Mαθαίνοντας design patterns", παρουσιάζω την χρησιμότητα του factory, με ένα πλήρες παράδειγμα...που θα σας ανοίξει την όρεξη....

Δευτέρα, 11 Φεβρουαρίου 2008 10:08 μμ by buzz

# re: [Μαθαίνοντας Design Patterns] Factory

Πολυ καλό Post ... Έχει όμως ένα ελλάτωμα... Όταν το διαβάσεις πεινάς... Stick out tongue

Τρίτη, 12 Φεβρουαρίου 2008 2:15 πμ by djsolid

# re: [Μαθαίνοντας Design Patterns] Factory

Heheh... Όπως κατάλαβες το νέο μου επιχειρηματικό πλάνο βασίζεται σε αλυσίδα καταστημάτων Σουβλαντζίδικων ;P

Τρίτη, 12 Φεβρουαρίου 2008 2:19 πμ by Aggelos Mpimpoudis

# re: [Μαθαίνοντας Design Patterns] Factory

Τουλάχιστον δεν το λες "καλαμάκι".. :P Ωραίο παράδειγμα πάντως, μπράβο!

Τρίτη, 12 Φεβρουαρίου 2008 2:41 πμ by Panagiotis Kefalidis

# re: [Μαθαίνοντας Design Patterns] Factory

Hehehe...μην μου βάζεις ιδέες για το abstract factory :P

thx m8!

Τρίτη, 12 Φεβρουαρίου 2008 2:54 πμ by Aggelos Mpimpoudis

# re: [Μαθαίνοντας Design Patterns] Factory

Δηλαδή, αν κατάλαβα καλά, αναφερόμαστε σε πρότυπο ανάπτυξης προγράμματος σύμφωνα με Client-Interface-Implementation ? Έτσι ώστε αλλάζοντας μόνο το Implementation να απαιτείται η ίδια κάθε φορά συμπεριφορά στο client programm?

Sorry, αν είμαι λίγο μπερδεμένος αλλά ίσα που το αγγίξαμε στο τρέχον εξάμηνο αυτό το ζήτημα...

Τρίτη, 12 Φεβρουαρίου 2008 3:25 πμ by StormRider

# re: [Μαθαίνοντας Design Patterns] Factory

Χμ...αυτό που λες εσύ το κάνατε σε μάθημα δομών δεδομένων; Μάλλον θα μιλάς για την βασική θεωρία του μαθήματος, όπου μιλήσατε για αφηρημένους τύπους δεδομένων (Abstract data types). Για παράδειγμα, αν έχεις μία συνδεδεμένη λίστα και κάνεις την πράξη εισαγωγής, καλείς την συνάρτηση και εσένα δεν σε ενδιαφέρει αν από κάτω υπάρχει πίνακας ή κόμβοι δεικτών. O client ξέρει μόνο την λειτουργία χωρίς να ξέρει την υλοποίηση. Αυτό για να ξεχωρίσουμε στα γρήγορα την έννοια των patterns με structures.

Αν λοιπόν αναφέρεσαι σε αυτό, τα design patterns, είναι σχεδιαστικές λύσεις οι οποίες στηρίζονται στις δομές δεδομένων και στην ουσία, ναι, εξυπηρετείται αυτός ακριβώς ο σκοπός που αναφέρεις. Απλά με αυτό το pattern πετυχαίνεις να λύσεις και κάποια επιπλέον σχεδιαστικά προβλήματα.

Αν απάντησα έστω και λίγο στην ερώτηση, I am glad. Αν όχι, ευχαρίστως να ακούσουμε και άλλες απόψεις. Όπως είπα και στο πρώτο blogpost, εδώ είμαστε για να μάθουμε όλοι ;)

Τρίτη, 12 Φεβρουαρίου 2008 4:26 πμ by Aggelos Mpimpoudis

# re: [Μαθαίνοντας Design Patterns] Factory

Εύγε Αγγελε! Υπέροχο post με μεγάλη φαντασία! Και για τη συμβουλή σου για το core reference, συμφωνώ απολύτως. Φαντάσου οτι το core reference *ακόμα* δεν *θελω* να το διαβάσω! Προτιμώ το Head First με την σερβιτόρα του! :)

Τρίτη, 12 Φεβρουαρίου 2008 11:57 πμ by Σωτήρης Φιλιππίδης

# re: [Μαθαίνοντας Design Patterns] Factory

:):):) Έτσι... Γενικά θέλοντας να μάθουμε κάτι σκεφτόμαστε ότι ένα βιβλίο θα περιέχει αυτό ακριβώς που θέλουμε. Ταυτόχρονα όμως, σκεφτόμαστε ότι μιας και θα δώσουμε που θα δώσουμε τόσα λευτά για ένα βιβλίο, ε ας πάρουμε το core reference μιας και είναι η βίβλος, να μας μείνει και για πάντα. Ε μετά βρισκόμαστε στο σημείο - 0 και παλι, ψάχνοντας ένα βιβλίο με λιγότερους κανόνες και περισσότερα παραδείγματα :P:P

Για να λέμε πάντως και τα πράγματα με το όνομά τους, μετά από την πρώτη επαφή με design patterns, το βιβλίο των GoF είναι must, όχι τόσο στον κώδικα (που έιναι C++ btw) αλλά για τις αναλύσεις του.

Τρίτη, 12 Φεβρουαρίου 2008 2:59 μμ by Aggelos Mpimpoudis

# re: [Μαθαίνοντας Design Patterns] Factory

@grnemo: Ναι σωστά αυτό το κάναμε στις Δομές Δεδομένων και πιστεύω με κάλυψες αρκετά πάνω στο θέμα.

Ωστόσο διαβάζοντας το πρώτο μέρος του Design Patterns είδα την αναφορά στο "πρότυπο Sigleton" και μου ρθε στο μυαλό Java GUI. Συγκεκριμένα θυμάμαι να γίνεται χρήση του προτύπου για να μην σηκώνεται twice ένα instance του JFrame μας. Πηγαίνοντας παρακάτω φτάνω στην ερώτησή μου: Design Pattern μπορούμε να θεωρήσουμε και την σχεδίαση προγράματος σύμφωνα με το Model-View-Controller ? Η' αυτό ξεφεύγει και ανήκει σε αυτό που -εγώ- έχω στο μυαλό μου ως UML ?

Ευχαριστώ για την προηγούμενη απάντηση ξεκαθαρίζουν αρκετά πράγματα, πολύ γρήγορα :)

Τετάρτη, 13 Φεβρουαρίου 2008 2:01 πμ by StormRider

# re: [Μαθαίνοντας Design Patterns] Factory

StormRider αυτό ακριβώς που ανέφερες για το JFrame, είναι από τα χαρακτηριστικότερα παραδείγματα Singleton pattern για UI. :)

Model-View-Controller είναι ένα αρκετά παλιό pattern, το οποίο χρησιμοποιέται σε πάρα πολλές περιπτώσεις (Web, Desktop, Mobile etc). Σημαίνει διαχωρισμός παρουσίασης δεδομένων, επεξεργασίας και αλληλεπίδρασης με γεγονότα (όπως ενέργειες του χρήστη). Ναι, λοιπόν είναι ένα design pattern αρχιτεκτονικής το οποίο λύνει προβλήματα που προκύπτουν, όταν η εφαρμογή μας μεγαλώνει σε έκταση και γίνεται πολύπλοκη. Για παράδειγμα (αν δεν κάνω λάθος) το Java Swing έχει έτοιμη υλοποίηση MVC.

H UML είναι κάτι το τελείως διαφορετικό. Είναι καταρχάς γλώσσα. Μπορείς να δεις περισσότερες πληροφορίες εδώ.

http://en.wikipedia.org/wiki/Unified_Modeling_Language

Μιας και το ανέφερες, σε επόμενο μου post, φεύγοντας από τα creation patterns, θα μιλήσω για model - view - controller. Είναι κάτι που το έχω κοιτάζω αυτόν τον καιρό λόγω μιας εργασίας στην σχολή (Web Site). Προς το παρόν στα επόμενα posts, θα εξετάσουμε δύο ακόμα creation patterns και μετά θα δούμε το MVC. Stay Tuned.

Thx!!!

Τετάρτη, 13 Φεβρουαρίου 2008 2:49 πμ by Aggelos Mpimpoudis

# re: [Μαθαίνοντας Design Patterns] Factory

Nice post... thanks for sharing

Τρίτη, 9 Σεπτεμβρίου 2008 10:14 πμ by Net Framework Development

Leave a Comment

(required) 
(required) 
(optional)
(required) 
Submit