Science Wiki
Register
Advertisement

Σχεδιαστικόν Πρότυπον

design pattern



Ένα σχεδιαστικό πρότυπο ορίζεται ως μία αποδεδειγμένα καλή λύση που έχει εφαρμοστεί με επιτυχία στην επίλυση ενός επαναλαμβανόμενου προβλήματος Σχεδίασης Συστημάτων Λογισμικού.


Ετυμολογία[]

Η ονομασία " Σχεδιαστικό" σχετίζεται ετυμολογικά με την λέξη "σχέδιο ".


Εισαγωγή[]

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

Ιστορικό[]

Κατά τα τέλη της δεκαετίας του 1970 ένας αρχιτέκτονας ονόματι Κρίστοφερ Αλεξάντερ επιχείρησε να αναζητήσει και να καταγράψει αποδεδειγμένα ποιοτικούς σχεδιασμούς στον τομέα των κατασκευών.

Έτσι μελέτησε πολλές διαφορετικές κατασκευές που εξυπηρετούσαν τον ίδιο σκοπό και προσπάθησε να ανακαλύψει κοινά στοιχεία, τα οποία κατηγοριοποίησε σε σχεδιαστικά πρότυπα.

Το 1987 η ιδέα της εύρεσης σχεδιαστικών προτύπων εφαρμόστηκε για πρώτη φορά στη μηχανική λογισμικού και μέχρι τα μέσα της δεκαετίας του '90 η εν λόγω έννοια είχε καθιερωθεί και εξαπλωθεί, προσανατολισμένη πλέον προς τον αντικειμενοστρεφή προγραμματισμό. Ιδιαίτερα σημαντική εξέλιξη προς αυτή την κατεύθυνση υπήρξε η έκδοση του βιβλίου Design Patterns: Elements of Reusable Object-Oriented Software των Erich Gamma, Richard Helm, Ralph Johnson και John Vlissides, το 1994. Οι τέσσερις αυτοί συγγραφείς αναφέρονται στη βιβλιογραφία ως "Συμμορία των Τεσσάρων" (Gang of Four) λόγω αυτού του βιβλίου.

Πρότυπα[]

Συνήθως τα σχεδιαστικά πρότυπα κατηγοριοποιούνται σε κατασκευαστικά (creational), δομικά (structural) και συμπεριφορικά (behavioral). Η κατηγοριοποίηση αυτή απαντάται ήδη από την εποχή της Συμμορίας των Τεσσάρων. Τα παραδείγματα κώδικα που παρέχονται παρακάτω είναι σε γλώσσα προγραμματισμού Java.

Κατασκευαστικά πρότυπα[]

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

Factory[]

Το πρότυπο αυτό συγκεντρώνει σε μία κατάλληλη κλάση, το Factory, όλη τη λειτουργικότητα κατασκευής στιγμιοτύπων μίας σειράς κλάσεων που κληρονομούν κάποια κοινή Υπερκλάση ή υλοποιούν την ίδια Διασύνδεση. Έτσι το πρόγραμμα μπορεί να καλεί τις Μεθόδους του Factory για να λάβει το ζητούμενο κατά περίπτωση αντικείμενο, χωρίς να χρειάζεται το ίδιο να γνωρίζει κάθε πιθανό τύπο δεδομένων. Με αυτόν τον τρόπο το πρόγραμμα είναι κλειστό ως προς πιθανές επεκτάσεις ενώ το Factory είναι ανοικτό ως προς αυτές, καθώς μόνο ο δικός του κώδικας χρειάζεται να τροποποιηθεί σε περίπτωση π. χ. προσθήκης μίας νέας κλάσης.

Το Factory συνήθως παρέχει μία μέθοδο για κάθε δυνατό τύπο επιστροφής, αλλά μία παραλλαγή ονόματι παραμετροποιημένο Factory παρέχει μία μοναδική μέθοδο η οποία επιλέγει το αντικείμενο που θα δημιουργήσει και θα επιστρέψει αναλόγως με την τιμή ενός ορίσματος που δέχεται.

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

Υπάρχει ωστόσο και μία εναλλακτική, αρκετά διαφορετική περίπτωση όπου, αντί το Factory να δηλώνεται ως κάποια/ες διακριστή/ες κλάση/εις, αποτελείται απλώς από μία ή περισσότερες στατικές μεθόδους της κλάσης από την οποία πρέπει να κατασκευάζει αντικείμενα (έστω της κλάσης Α). Τότε ο κατασκευαστής (constructor) της κλάσης δηλώνεται ως ιδιωτική μέθοδος ώστε κάθε απόπειρα του εξωτερικού προγράμματος να δημιουργήσει στιγμιότυπα της Α να γίνεται αναγκαστικά μέσω των μεθόδων Factory οι οποίες επιστρέφουν ένα νέο αντικείμενο τύπου Α.

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

interface Logger
{
   public void log(String msg);
}

class ConsoleLogger implements Logger
{
   public void log(String msg)
   {
      System.err.println("\nConsole logging..." + msg + "\n");
   }
}

class FileLogger implements Logger
{
   public void log(String msg)
   {
       System.out.println("\nFile logging..." + msg + "\n");
   }
}

public class LoggerFactory
{
   public Logger getLogger(String choice)
   {
       if(choice.equals("FileLogger"))
          return new FileLogger();
       else if(choice.equals("ConsoleLogger"))
          return new ConsoleLogger();
       else
       {
          System.err.println("\nError. Exiting...");
          return null;
       }
   }
}

public class LogTest
{
    public static void main(String[] args)
    {
       if(args.length != 1)
       {
           System.out.println("\nError. Exiting...");
           return;
       }
       LoggerFactory fac = new LoggerFactory();
       String choice = args[0];
       Logger logg = fac.getLogger(choice);
       logg.log("Log This!");
    }
}

Στον κώδικα αυτόν η κλάση LoggerFactory είναι η μόνη που γνωρίζει τους διαφορετικούς τύπους δεδομένων οι οποίοι υλοποιούν τη διασύνδεση Logger, άρα είναι και το μόνο σημείο του κώδικα που χρειάζεται να τροποποιηθεί σε περίπτωση που η Logger επεκταθεί με ακόμα μία κλάση. Το εξωτερικό πρόγραμμα, η κλάση LogTest, χειρίζεται απλώς ένα αντικείμενο του γενικού τύπου Logger και αφήνει στο Factory την απόφαση για τον πραγματικό τύπο του, αναλόγως με ένα όρισμα γραμμής εντολών που δίνεται από το χρήστη.

Ακολουθεί ένα παράδειγμα ορισμού του Factory ως μεθόδου μίας κλάσης την οποία πρέπει να παράγει:

class Complex
{
     public static Complex fromCartesian(double real, double imag) {
         return new Complex(real, imag);
     }
 
     public static Complex fromPolar(double modulus, double angle) {
         return new Complex(modulus * cos(angle), modulus * sin(angle));
     }
  
     private Complex(double a, double b) {}
}
  
Complex c = Complex.fromPolar(1, pi); //Αντί για την τυπική κλήση Complex c = new Complex(...) η 

//οποία θα μπορούσε να γίνει αν ο κατασκευαστής ήταν δημόσιος

Abstract Factory[]

Singleton[]

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

public class A
{
   private static A instance;
   private A() {} //Ο κατασκευαστής ο οποίος μπορεί να κληθεί μόνο από κώδικα της ίδιας της Α
   public static A getAObject()
   {
      if (instance == null)
      {
         instance = new A();
      }
      return instance;
   }
}

Η Α περιέχει ένα στατικό γνώρισμα instance τύπου Α και μία στατική δημόσια μέθοδο getAObject η οποία ελέγχει αν στο γνώρισμα αυτό έχει ανατεθεί τιμή. Αν ναι επιστρέφει το ίδιο το γνώρισμα, διαφορετικά δημιουργεί ένα νέο στιγμιότυπο της ίδιας της κλάσης Α και το αναθέτει στο πεδίο instance προτού επιστρέψει το τελευταίο. Ο κατασκευαστής είναι ιδιωτικός ώστε να παρακάμπτεται αναγκαστικώς από το εξωτερικό πρόγραμμα και να χρησιμοποιείται πάντα η μέθοδος getAObject.


Εσωτερική Αρθρογραφία[]

Βιβλιογραφία[]

  • Σχεδιαστικά Πρότυπα, Απόστολος Ζάρρας, Λέκτορας Πανεπιστημίου Ιωαννίνων,
  • Core Techniques and Algorithms in Game Programming, Daniel Sanchez-Crespo Dalmeau, Εκδόσεις New Riders

Ιστογραφία[]


Ikl Κίνδυνοι ΧρήσηςIkl

Αν και θα βρείτε εξακριβωμένες πληροφορίες
σε αυτήν την εγκυκλοπαίδεια
ωστόσο, παρακαλούμε να λάβετε σοβαρά υπ' όψη ότι
η "Sciencepedia" δεν μπορεί να εγγυηθεί, από καμιά άποψη,
την εγκυρότητα των πληροφοριών που περιλαμβάνει.

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

Πρέπει να λάβετε υπ' όψη ότι
όλα τα άρθρα μπορεί να είναι ακριβή, γενικώς,
και για μακρά χρονική περίοδο,
αλλά να υποστούν κάποιο βανδαλισμό ή ακατάλληλη επεξεργασία,
ελάχιστο χρονικό διάστημα, πριν τα δείτε.



Επίσης,
Οι διάφοροι "Εξωτερικοί Σύνδεσμοι (Links)"
(όχι μόνον, της Sciencepedia
αλλά και κάθε διαδικτυακού ιστότοπου (ή αλλιώς site)),
αν και άκρως απαραίτητοι,
είναι αδύνατον να ελεγχθούν
(λόγω της ρευστής φύσης του Web),
και επομένως είναι ενδεχόμενο να οδηγήσουν
σε παραπλανητικό, κακόβουλο ή άσεμνο περιεχόμενο.
Ο αναγνώστης πρέπει να είναι
εξαιρετικά προσεκτικός όταν τους χρησιμοποιεί.

- Μην κάνετε χρήση του περιεχομένου της παρούσας εγκυκλοπαίδειας
αν διαφωνείτε με όσα αναγράφονται σε αυτήν

IonnKorr-System-00-goog



>>Διαμαρτυρία προς την wikia<<

- Όχι, στις διαφημίσεις που περιέχουν απαράδεκτο περιεχόμενο (άσεμνες εικόνες, ροζ αγγελίες κλπ.)


Advertisement