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

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

DESIGN PATTERNS

Μιας και εγώ πρόσφατα άρχισα να τα χρησιμοποιώ, θα πρότεινα για αρχή, να πούμε τι είναι στην πραγματικότητα design patterns και να εξετάσουμε μαζί μερικά patterns που χρησιμοποιούνται συχνά. Θα προσπαθήσω να τα πω όσο περιεκτικά μπορώ ώστε και εγώ να μαθαίνω μέσα από την αφαιρετικότητα και να αρκούν αυτά που γράφω για να ενισχύσω την διάθεσή σας να πειραματιστείτε και να διαβάσετε περισσότερα. Θα προσπαθώ να περιγράφω 2-3 patterns την εβδομάδα. Ή γλώσσα που θα χρησιμοποιώ δεν έχει καμία απολύτως σημασία μιας και εδώ μιλάμε για αντικειμενοστραφή προγραμματισμό και όχι για κάποια συγκεκριμένη γλώσσα (C++, Java, C#, ...)

Τι είναι design pattern;

Κάθε pattern περιγράφει ένα πρόβλημα το οποίο μας παρουσιάζεται συνέχεια στον χώρο μας. Στην συνέχεια περιγράφει την λύση που επιλύει το πρόβλημα με τέτοιο τρόπο που να μπορούμε να την ξαναχρησιμοποιήσουμε ξανά και ξανά με μηδενική προσπάθεια ( Ο χρόνος είναι χρήμα, οπότε κάνοντας τα design patterns κτήμα μας, u know the drill ;) ).

Στοιχεία pattern
  1. Όνομα
  2. Το πρόβλημα που λύνει
  3. Την λύση που προτείνει, περιγράφει, προδιαγράφει
  4. Τις συνέπειες μετά από την χρήση. Συνήθως σε ένα πρόγραμμα οι συνέπειες είναι ο χώρος και ο χρόνος. Οπότε κάθε φορά στον έναν ζυγό έχουμε επαναχρησιμοποίηση, λειτουργικότητα, επεκτασιμότητα και στον άλλον, κόστος σχεδίασης, χρόνο
Είδη

Τα design patterns κατηγοριοποιούνται με βάση δύο παραμέτρους. Εμβέλεια και σκοπός. Επιγραμματικά αναφέρω σκοπούς και εμβέλειες και θα αφήνω σε εσάς στο τέλος κάθε pattern τι είναι κάθε ένα ;)

  • Εμβέλεια
    Ανά Κλάση
    Ανά Αντικείμενο
  • Σκοπός
    Για δημιουργία
    Για δόμηση
    Για συμπεριφορά
Design Pattern 1#: Singleton

Singleton είναι το pattern που μας διαβεβαιώνει ότι η κλάση μας έχει μόνο ένα στιγμιότυπο. Επίσης παρέχεται ένας συγκεκριμένος τρόπος για να μπορούμε να το ανακτούμε από οπουδήποτε. Ας πούμε ένα παράδειγμα. Πείτε ότι έχετε πολλούς εκτυπωτές στο σύστημά σας. Παρόλα αυτά όταν πάτε να εκτυπώσετε, η εκτύπωσή σας περνάει από έναν printer spooler. Θα μπορούσαμε να βάλουμε μια global μεταβλητή ώστε να μπορούμε να ανακτήσουμε από παντού το αντικείμενο, αλλά δεν μας εμποδίζει κάτι από το να δημιουργήσουμε πολλαπλά στιγμιότυπα της κλάσης αυτής. Η λύση είναι λοιπόν, η ίδια η κλάση να κρατάει την πληροφορία για τον εαυτό της, το πως θα δημιουργηθεί, το πότε και πως θα μας επιστρέφει το ένα και μοναδικό instance της (εαν έχει δημιουργηθεί).

 class Singleton
  {
    private static Singleton instance;

    protected Singleton()
    {
    }

    public static Singleton Instance()
    {

      if (instance == null)
      {
        instance = new Singleton();
      }

      return instance;
    }

Share/Bookmark
Published Τρίτη, 18 Δεκεμβρίου 2007 4:11 μμ by Aggelos Mpimpoudis

Comments

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

Nice post!!

Αν, παρόλα αυτά, θέλουμε να δημιουργήσουμε ένα νέο instance σε ένα singleton object τρίτου κατασκευαστή, πάντα μπορούμε να χρησιμοποιήσουμε το Reflection

π.χ.

Singleton a = Singleton.Instance();

Singleton b = (Singleton)a.GetType().GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null).Invoke(new object[] { });

Τρίτη, 18 Δεκεμβρίου 2007 11:00 μμ by Δημήτρης Γκανάτσιος

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

Απλά αναφέρω, για να μην μπερδευτούμε, ότι αυτό που λές αν θεωρηθεί μέρος του pattern αντιβαίνει τελείως την σχεδιαστική αρχή που προδιαγράφει, καθώς αφενός δεν έχουμε πάντα c# ή java που έχουν reflection και αφετέρου ότι αυτό που λες το βλέπω σαν ένα workaround/παράκαμψη του pattern και όχι μέρος της λύσης στο πρόβλημα που αναφέρεται.

Για το τι είναι reflection και σε ποιές περιπτώσεις το χρησιμοπούμε διαβάζουμε τα posts του Δημήτρη here

http://www.studentguru.gr/blogs/dt008/archive/tags/reflection/default.aspx

WinkYes

Τετάρτη, 19 Δεκεμβρίου 2007 1:20 πμ by Aggelos Mpimpoudis

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

Δεν ανέφερα ότι είναι μέρος του pattern. Φυσικά και η λύση στο "single instance" είναι το singleton. Παρόλα αυτά, σε κάποιες περιπτώσεις, ίσως να θέλουμε να "παρακάμψουμε" την πρόθεση του developer που έχει φτιάξει κάποια κλάση, για τους δικούς μας σκοπούς. Anyway, το reflection σε αυτή την περίπτωση δεν είναι κι ό,τι καλύτερο, καθώς αυτός που το έγραψε το singleton (μιας και σε αυτό αναφερόμαστε) κατά πάσα ήξερε τι έκανε, αλλά ποτέ δεν ξέρεις που μπορεί να σου χρειαστεί μια τέτοια παράκαμψη.

Α, προσοχή, ποτέ μην μαρκάρετε μια singleton κλάση ως Serializable, γιατί άνετα μπορεί να προκύψει αντίγραφο της με χρήση serialization/deserialization σε ένα Stream.

Τετάρτη, 19 Δεκεμβρίου 2007 1:41 πμ by Δημήτρης Γκανάτσιος

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

Σωστός!!! Το έψαξα λίγο στο net. Δες τι workaround βρήκα:

   public class MySingleton implements Serializable {

       static MySingleton singleton = new

                                   MySingleton();

       private MySingleton() {

       }

       // This method is called immediately after an object of this class is deserialized.

       // This method returns the singleton instance.

       protected Object readResolve() {

           return singleton;

       }

   }

Cool!!!!

Τετάρτη, 19 Δεκεμβρίου 2007 1:58 πμ by Aggelos Mpimpoudis

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

αααααααααχχχχχχχ γιατί μου το γράφεις σε Java;;;; Stick out tongue

τέσπα, τσιμπήστε και τον αντίστοιχο με μια extension method σε C# 3.0 (btw, το ίδιο pattern μπορεί να χρησιμοποιηθεί και για deep copy ενός αντικειμένου)

προϋποθέσεις

1. το attribute [Serializable] στο Singleton

2. using System.IO;

3. using System.Runtime.Serialization.Formatters.Binary;

και έχουμε

public static Singleton Clone(this Singleton x)

       {

           MemoryStream ms = new MemoryStream();

           BinaryFormatter bf = new BinaryFormatter();

           bf.Serialize(ms, x);

           ms.Position = 0;

           Singleton obj = (Singleton)bf.Deserialize(ms);

           ms.Close();

           return obj;

       }

καλείται ως

Singleton a = Singleton.Instance();

Singleton b = a.Clone();

δείτε και αυτό, btw

http://msdn2.microsoft.com/en-us/library/ms954629.aspx

Τετάρτη, 19 Δεκεμβρίου 2007 2:09 πμ by Δημήτρης Γκανάτσιος

Leave a Comment

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