Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Εστω ότι έχω μια abstract class από την οποία κληρονομούνε 2 άλλες κλάσεις.

Το header file της κλασης αυτής είναι το εξής:

 

 

>class FΙ
{
protected:
string id;
string reference;

public:
//overloaded consructor
FI(string id,string reference);

string GetInstrumentID() ;
void SetInstrumentID(string id);

string GetReference();
void SetReference(string reference);

virtual void Print();

//pure virtual method
virtual double Pricing(FI* ptr_I)=0;

//default constructor
FI(void);
      ~FI(void);
};

 

και έχω για παράδειγμα άλλες 2 κλάσεις που κληρονομούνε από την παραπάνω

 

 

>class Eq :
public FI
{
double lastPrice;
string name;
double spotPrice;

public:
void Print(void);
string GetName();
double GetLastPrice();

void SetSpotPrice();
double GetSpotPrice();

virtual double Pricing(FI* ptr_I);

Eq(string id,string reference,double lastPrice, string name);
Eq(void);
virtual ~Eq(void);
};

class Bd :
public FI
{
//member fields
...........................

public:
Bd(void); //default constructor
Bd( string id,string reference,.........); //overloaded constructor


//member functions
       ...................................

virtual double Pricing(FI* ptr_I) ;

void Print(void); //prints out the member fields of Bond's instances

};

 

Θέλω την ιεαρχία αυτή να την υλοποιήσω και να την τεστάρω στην main χρησιμοποιώντας ενα Singleton Pattern. Τα διαφορετικά στιγμιότυπα των κλάσεων που δημιουργούνται θα τα αποθηκεύω σε ένα map, το οποίο θα πέρνει σαν κλειδι το string id της κλάσης FI και σαν Value έναν δείκτη σε FI, και θα αποφασίζει ποια κλάση πρεέπει να φτιάξει.

Αν δεν κάνω λάθος πρέπει να ναι κάτι τέτοιο η κλάση Singleton:

 

>class Singleton{

private :
map < string, FI * > MyMap;
Singleton() ; //constructor;

public:

static Singleton * getInstance();

};

 

Τα αντικείμενα που παίρνει το map, θα τα γεμίζω μέσα από τον constructor της Singleton? Η απο την μεθοδο getInstance?Πρέπει το κάθε αντικείμενο του map μετα να μπορεί να καλέσει σωστα τις virtual συναρτησεις που είναι ορισμένες στην abstract class FI, μιας και η κάθε υποκλάση έχει την δική της υλοποίηση των virtual methods..το θέμα είναι πως γίνεται αυτό σε SIngleton..

Δημοσ.

Αυτό που θέλεις δεν λέγεται Singleton αλλά Factory. Απο κει και πέρα το factory μπορεί ταυτόχρονα να είναι και Singleton (και ίσως και να βολεύει μάλιστα όσον αφορά το πώς θα γίνει να το "ρυθμίσεις") αλλά οι δυο έννοιες είναι τελείως διαφορετικές και ως τέτοιες πρέπει να τις αντιμετωπίζεις.

 

Τώρα, όσον αφορά το map που λες: γενικά η ιδέα είναι αυτή, αλλά εδώ πρέπει να σκεφτείς το πώς ακριβώς το factory θα δημιουργεί τα αντικείμενα που επιστρέφει. Αυτή τη στιγμή μπορώ να σκεφτώ τις εξής περιπτώσεις:

 

  1. Για κάθε είδος αντικειμένου, το factory διαθέτει μια Factory Method την οποία καλεί (στην ουσία πετώντας το μπαλάκι σ' αυτήν) όποτε χρειαστεί. Ρύθμιση του factory επομένως σημαίνει να του πούμε ποιές είναι αυτές οι factory methods.
  2. Για κάθε είδος αντικειμένου, το factory διαθέτει ένα "πρωτότυπο" αυτού του είδους το οποίο μπορεί είτε α) να επιστρέψει αυτούσιο, οπότε στην ουσία έχεις ένα factory που δίνει singletons, είτε β) να καλέσει μια clone() method του πρωτοτύπου (την οποία όλα τα πρωτότυπα πρέπει να έχουν) με την οποία δημιουργεί ένα αντίγραφο του πρωτοτύπου όποτε χρειαστεί. Ρύθμιση του factory επομένως σημαίνει να του πούμε ποιά είναι τα πρωτότυπα.

 

Εδώ τώρα να σημειώσω ότι αν θέλεις να γίνεις πολύ engineer, μπορείς να κανονίσεις ούτως ώστε το ίδιο το factory να είναι παραμετροποιήσιμο με την ακριβή "στρατηγική" που θα ακολουθεί είτε κατά το compilation (π.χ. είναι class template που κάνει inherit μια type template parameter η οποία κάνει implement κατάλληλες μεθόδους) είτε κατά το runtime (οπότε το factory για τη λειτουργία του χρησιμοποιεί τη στρατηγική που θα του υποδείξεις).

 

Φαντάζομαι εσύ έχεις στο μυαλό σου την προσέγγιση #1 (με factory methods) η οποία είναι και πιο προφανής στη σκέψη. Επομένως το value_type του map μπορεί να είναι

 

>class Factory {
 public:
     typedef FI* (*FactoryMethodType)();
 private:
     map<string, FactoryMethodType> MyMap;
};

 

Τώρα το παραπάνω είναι μεν μια αρχή αλλά σηκώνει ακόμα άπειρη βελτίωση. Πρώτον, γιατί να μην κάνουμε το factory template?

 

>
template<class Product>
class Factory {
 public:
     typedef Product* (*FactoryMethodType)();
 private:
     map<string, FactoryMethodType> MyMap;
};

 

Δεύτερον, το παραπάνω μπορεί να ρυθμίσει το map μόνο με pointers σε free functions που δεν παίρνουν παραμέτρους και επιστρέφουν Product*. Αυτό αφήνει απέξω function objects και member function οι οποίες επίσης θα ήταν κατάλληλες για τη δουλειά (όλα τα παραπάνω μαζί ονομάζονται functors).

 

Πλέον με τη C++11 μπορείς να τα έχεις όλα ως εξής:

 

>
template<class Product>
class Factory {
 public:
     typedef std::function<Product*()> FactoryMethodType;
 private:
     map<string, FactoryMethodType> MyMap;
};

 

Σ' αυτό το σημείο σου προτείνω να κάνεις το MyMap public και να κάνεις μερικά factories τα οποία θα ρυθμίζεις manually με factory.MyMap.insert() πριν τα χρησιμοποιήσεις για να πάρεις το κολάι. Για παράδειγμα (πάλι C++11 για ευκολία),

 

>Factory<FI> factory;
factory.MyMap["Eq"] = []() { return new Eq(); };
factory.MyMap["Bd"] = []() { return new Bd(); };

Στη συνέχεια μπορούμε να δούμε και εναλλακτικούς τρόπους ρύθμισης.

Δημοσ.

Οχι Factory, πρέπει να γίνει η υλοποίηση με Singleton. Εχω ένα project με την abstract class FI, και τις Eq , Bd που κληρονομουν από αυτήν και υλοποιούν κάποιες virtual συναρτήσεις. Το ζητούμενο για να μπορέσω να καταλάβω πως λειτουργεί το pattern , είναι να φτιάξω μια επιπλέον κλάση Singleton, στην οποία εκεί μέσα θα έχω το map στο οποίο θα αποθηκεύω και θα διαχειρίζομε τα διαφορετικά αντικείμενα των κλάσεων παιδια?

Δημοσ.

Αυτο που περιγραφεις ειναι factory. Ενα object που δημιουργει αλλα objects.

 

Το singleton ειναι μια τεχνικη που σου επιτρεπει να εχεις μια κλαση που να τηνκανεις share.

πχ

>

template <class T>
struct Singleton
{
static T* GetInstance()
{
	static T* _inst = NULL;
	if(!_inst)
		_inst = new T;
	return _inst;
}
};

struct A
: Singleton<A>
{
};
struct B
: Singleton<B>
{
};

void Somewhere()
{
std::cout
	<< "First A instance:"
	<< A::GetInstance()
	<< std::endl
	<< "Second A instace:"
	<< A::GetInstance()
	<< std::endl
	<< "First B instace:"
	<< B::GetInstance()
	<< std::endl
	<< "Second B instance:"
	<< B::GetInstance();
}

int  main(void)
{
std::cout
	<< "First A instance:"
	<< A::GetInstance()
	<< std::endl
	<< "Second A instace:"
	<< A::GetInstance()
	<< std::endl
	<< "First B instace:"
	<< B::GetInstance()
	<< std::endl
	<< "Second B instance:"
	<< B::GetInstance();

Somewhere();

return 0;
}

 

Δημοσ.

Οχι Factory, πρέπει να γίνει η υλοποίηση με Singleton. Εχω ένα project με την abstract class FI, και τις Eq , Bd που κληρονομουν από αυτήν και υλοποιούν κάποιες virtual συναρτήσεις. Το ζητούμενο για να μπορέσω να καταλάβω πως λειτουργεί το pattern , είναι να φτιάξω μια επιπλέον κλάση Singleton, στην οποία εκεί μέσα θα έχω το map στο οποίο θα αποθηκεύω και θα διαχειρίζομε τα διαφορετικά αντικείμενα των κλάσεων παιδια?

 

Απ' όλα αυτά που έγραψα εσύ αυτό κατάλαβες; :unsure:

 

Αυτό που περιγράφεις είναι factory. Το factory μπορείς να το υλοποιήσεις ως singleton, μπορείς και όχι. Είναι δύο τελείως ασύνδετα πράγματα.

 

Για να καταλάβεις πώς λειτουργεί το pattern καλύτερα ν' αφήσεις τις όποιες εντυπώσεις έχεις στο μυαλό σου (που είναι λάθος) και να διαβάσεις αυτό ή τουλάχιστον τα links που έδωσα. Γιατί τώρα είναι σα να λες ότι πρέπει να γίνει η υλοποίηση του οχήματος με κόκκινο χρώμα.

 

Εναλλακτικά, αν σ' ενδιαφέρει μόνο το πως γίνεται Singleton, άσε όλα τα υπόλοιπα απέξω από τη συζήτηση να μιλήσουμε π.χ. για το πώς θα γίνει Singleton μια class που είναι τελείως άδεια.

 

Μπορώ όμως την abstract class να την υλοποιήσω με λογική Singleton Pattern?

 

Το singleton είναι μια pattern δημιουργίας (διαχειρίζεται τον τρόπο με τον οποίο δημιουργούνται αντικείμενα μιας class). Απο μια class που είναι abstract εξ ορισμού δεν μπορείς να δημιουργήσεις αντικείμενα.

 

@παπί:

 

Μέχρι τώρα απέφυγα να αρχίσω να λέω ότι το Singleton είναι πάντα λάθος εκτός κι αν είσαι world class επιπέδου προγραμματιστής οπότε μάλλον κάτι θα ξέρεις γι' αυτό που πας να κάνεις -- γενικά απέφυγα να αναφερθώ λεπτομερώς στο Singleton γιατί είναι ένα τεράστιο κεφάλαιο αποτελούμενο από 99% παγίδες.

 

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

Δημοσ.

Καλα οκ. Δν εχω ασχοληθει με pattern. Εκανα ενα googling ειδα πως δουλευει και εβγαλα συμπερασμα (ετσι δουλευω happy.gif ), μπορει και να ειναι λαθος.

 

Τεσπα λες "Το μόνο χαρακτηριστικό του Singleton που είναι επιθυμητό είναι πως δεν μπορείς να δημιουργήσεις πάνω από ένα instance" , αυτο δεν κανει και το παραδειγμα μου;(οκ αν καλεσεις τον new τοτε θα εχεις αλλο instance, αλλα μεσου του γετινστανψε δεν μπορεις να βγαλεις αλλο ινστανς. Ή κανω κατι λαθος; )

Δημοσ.

Ναι η getInstance() πάντα το ίδιο θα επιστρέφει αλλά δεν είναι αυτό το θέμα. Ειδάλλως βάζαμε μια τέτοια σε οποιαδήποτε class και αυτομάτως γινόταν singleton.

 

Κατ' ελάχιστον πρέπει να είναι private όλοι οι constuctors (και ο copy constructor) όπως επίσης και ο assignment operator. Και πάλι όμως αυτή είναι μόνο η κορυφή του παγοβούνου.

Δημοσ.

Επανέρχομαι δίνοντας ένα απλό παράδειγμα που βρήκα στο νετ και είναι αυτό που θέλω να κάνω..

Τι κάνω λάθος όμως ??? :fear: :shock:

 

 

>#include <iostream>
#include <stdio.h>

using namespace std;

template <class T>
class Singleton 
{
public: 
   ~Singleton(void) {};
   static T& GetService(void) {return *Instance;}
protected:
   Singleton<T>(void) {};
   static T* Instance;
};

template <class T>
T* Singleton<T>::Instance = 0;


class ApplicationManager : public Singleton<ApplicationManager>
{
public:
   ~ApplicationManager(void)
   {    }
    
   virtual void foo( void ) = 0;
    
protected:
    
   ApplicationManager(void)
   {    }
};

class MyApplicationManager : public ApplicationManager
{
public:    

   MyApplicationManager(void)
   {    }
    
   virtual void foo( void )
   {
       cout << "MyApplicationManager" << endl;
   }
};


   
   
   int main( void )
   {
   ApplicationManager  * mgr_;
   mgr_->foo( );
   system("pause");
   return 0;    
       
   }

Δημοσ.

Επανέρχομαι δίνοντας ένα απλό παράδειγμα που βρήκα στο νετ και είναι αυτό που θέλω να κάνω..

Τι κάνω λάθος όμως ??? :fear: :shock:

 

 

 

>#include <iostream>
#include <stdio.h>

using namespace std;

template <class T>
class Singleton 
{
public: 
   ~Singleton(void) {};
   static T& GetService(void) {return *Instance;}
protected:
   Singleton<T>(void) {};
   static T* Instance;
};

template <class T>
T* Singleton<T>::Instance = 0;


class ApplicationManager : public Singleton<ApplicationManager>
{
public:
   ~ApplicationManager(void)
   {    }
    
   virtual void foo( void ) = 0;
    
protected:
    
   ApplicationManager(void)
   {    }
};

class MyApplicationManager : public ApplicationManager
{
public:    

   MyApplicationManager(void)
   {    }
    
   virtual void foo( void )
   {
       cout << "MyApplicationManager" << endl;
   }
};


   
   
   int main( void )
   {
   ApplicationManager  * mgr_;
   mgr_->foo( );
   system("pause");
   return 0;    
       
   }

 

Με Singleton δεν έχω ασχοληθεί (πλην κάποιων custom υλοποιήσεων σε Java/Android), από ότι βλέπω όμως ορίζεις το mgr_ σου ως δείκτη (*mgr_) σε ένα μη δεσμευμένο αντικείμενο (ApplicationManager) και καλείς ύστερα την virtual void διαδικασία foo που η διεύθυνση της δείχνει σε NULL.

 

Υ.Γ.

Ρίξε μια ματιά στο τελευταίο post αυτής της σελίδας όπου υπάρχει μια απλή υλοποίηση Singleton σε C++ (αρκούντως τεκμηριωμένη).

 

Καλή συνέχεια!! :)

Δημοσ.

Επανέρχομαι δίνοντας ένα απλό παράδειγμα που βρήκα στο νετ και είναι αυτό που θέλω να κάνω..

Τι κάνω λάθος όμως ??? :fear: :shock:

 

Το λάθος είναι αυτό που είπε ο Directx: o pointer mgr_ δεν έχει αρχικοποιηθεί οπότε όταν τον κάνεις dereference με το -> έχουμε UB (undefined behavior) -- και στην προκειμένη αυτό σημαίνει μπουμ.

 

(@Directx: δεν είναι null ο pointer, έχει κάποια άγνωστη τιμή η οποία σχεδόν σίγουρα δεν είναι μηδέν).

 

Δε θα προτείνω κάποια διόρθωση γιατί ο κώδικας που παραθέτεις δε βγάζει λογικό νόημα, οπότε το πρόβλημα είναι μεγαλύτερο από το ότι σου σκάει στα χέρια (παρένθεση: αν παίρνεις online παραδείγματα χωρίς να μπορείς μόνη σου να κρίνεις το ορθό τους αυτομάτως εμπιστεύεσαι αυτόν που έκανε post το παράδειγμα ότι ξέρει τι κάνει -- πράγμα που κάθε άλλο παρά σίγουρο είναι).

 

Θα πω δυο λόγια για το singleton, αλλά πριν ξεκινήσω σε παρακαλώ διάβασε αυτό για να καταλάβεις γιατί σχεδόν πάντα το Singleton είναι πρόβλημα και όχι λύση.

 

Η ιδέα του Singleton είναι ότι δεν πρέπει κανένας να μπορεί να διαχειριστεί τη δημιουργία και καταστροφή αντικειμένων μιας class εκτός από την ίδια την class. Η class θα δίνει μια μέθοδο του στυλ getInstance() η οποία θα είναι και ο μόνος τρόπος κώδικας "εξωτερικά" αυτής να πάρει στα χέρια του ένα αντικείμενο της class (η getInstance() μπορεί να επιστρέφει pointer, μπορεί και κανονικό αντικείμενο -- είναι θέμα επιλογής).

 

Επομένως:

 

Πρόβλημα #1: Η Singleton έχει public destructor!

 

Αυτό σημαίνει ότι μπορεί κανείς να γράψει

 

>myclass c = Singleton<myclass>::GetService(); // ας υποθέσουμε ότι επιστρέφει κάτι σωστό
c.~c(); // αυτό επιτρέπεται!
delete &c; // κι αυτό επιτρέπεται!

 

Πρόσεξε παραπάνω πως είπα "...δεν πρέπει κανένας να μπορεί να διαχειριστεί τη δημιουργία και καταστροφή...".

 

Μόνο και μόνο απ' αυτό είναι προφανές (σε μένα τουλάχιστον) ότι όποιος έγραψε το template Singleton απλά δεν έχει καταλάβει τι γίνεται.

 

Πρόβλημα #2: Η Singleton έχει protected constructor!

 

Όταν λέμε ότι "δεν πρέπει κανένας να μπορεί να διαχειριστεί τη δημιουργία και καταστροφή αντικειμένων μιας class εκτός από την ίδια την class", εννοούμε κανείς -- ούτε και όσοι κάνουν derive από αυτήν. Πράγμα το οποίο αυτομάτως σημαίνει ότι είναι φύσει αδύνατον να φτιάξεις σωστό singleton με τη λογική του "κάνε derive από αυτή την class". Πράγμα που σημαίνει ότι ο constructor δεν έχει νόημα να είναι ο,τιδήποτε άλλο εκτός από private. Που τελικά σημαίνει ότι δεν υπάρχει derivation όταν μιλάμε για singletons.

 

Όπως έλεγα: όποιος το έγραψε δεν έχει καταλάβει τι γίνεται.

 

Πρόβλημα #3: ...και μετά μας πήρε ο κατήφορος

 

Έρχεσαι καλή ώρα εσύ στο τέλος και φτιάχνεις μια ιεραρχία που κάνει derive από το Singleton<ApplicationManager> (μόνο και μόνο αυτό είπαμε είναι no go) και το κερασάκι στην τούρτα είναι ότι η MyApplicationManager έχει public constructor!

 

Το οποίο σημαίνει ότι όλα αυτά που έγραψες παραπάνω πάνε φούντο γιατί τώρα οποιοσδήποτε μπορεί να γράψει MyApplicationManager mam; και να κάνει όσα αντικείμενα της class θέλει.

 

Δεν ξέρω πώς πρέπει να σε παρακαλέσω... stop the madness. Μη πιάνεις πληκτρολόγιο αν πρώτα δεν έχεις καταλάβει την ιδέα πίσω από κάτι.

 

Κατακλείδα

 

Μπορείς σε παρακαλώ να μας εξηγήσεις ποιός ακριβώς είναι ο σκοπός σου? Γιατί έχεις φαγωθεί να κάνεις Singleton? Τι σε πειράζει να κάνεις μια global μεταβλητή του τύπου που θέλεις και να μην ξανακαλέσεις πουθενά τον constructor αυτού του τύπου ("συμφωνία κυρίων")?

 

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

 

Ρίξε μια ματιά στο τελευταίο post αυτής της σελίδας όπου υπάρχει μια απλή υλοποίηση Singleton σε C++ (αρκούντως τεκμηριωμένη).

 

Δεν έχω να πώ τίποτα παραπάνω για την ποιότητα του κώδικα σ' εκείνο το post πέρα από αυτό:

 

>protected:
// Default ctor, copy-ctor and assignment operators should be as PRIVATE so that nobody
// from outside can call those functions and instantiate it
Singleton();
Singleton(const Singleton&);

 

Τελικά από το πολύ private κατάφερε να γίνει protected.

Δημοσ.

>class Singleton
{
public:
static Singleton& Instance()
{
	static Singleton obj;
	return obj;
}

std::string Name() const
{ return name_; }
private:
Singleton()
: name_("Klain Main")
{}
       ~Singleton();

// Disable copy-con and as-op
Singleton(const Singleton& obj);
Singleton& operator=(const Singleton& obj);

std::string name_;
};

#include <string>
#include <iostream>

int main()
{
std::cout << Singleton::Instance().Name() << '\n';
}

 

Η παραπάνω υλοποίηση είναι μια απλή μορφή ενός singleton pattern. Σε singleton pattern ο constructor παντα είναι private και οι copy-con και as-op είναι private και απενεργοποιημένοι. Αυτά στην πιο απλή μορφή. Τον κώδικα δεν τον τσέκαρα για τυχών λάθη επειδή δεν βρίσκομαι σπίτι και εδώ δεν έχω μεταγλωττιστή. Αυτά τα λίγα.

 

Παρειπηπτώντως(έτσι γράφεται; ) αυτό το singleton είναι γνωστό και ως Meyers Singleton. Ντροπή και αίσχος όποιος δεν γνωρίζει τον Scott Meyers :-D :-D :-D

 

Y.Γ:ψάντωντας να βρώ τι ξέχασα(μεσημέρι είναι και πλέον δεν ασχολούμαστε με το άθλημα ενεργά πλέον) βρήκα ένα άρθρο σχετικά με singleton το οποίο είχε μια template υλοποίηση που πιθανόν να ενδιαφέρει τον topic starter.

 

>template <typename T>
class Singleton
{
public:
static T& Instance()
{
	static T obj;
	return obj;
}
private:
Singleton();
       ~Singleton();

Singleton(const Singleton& obj);
Singleton& operator=(const Singleton& obj);
};

 

 

 

Οπότε δεν θα χρειαστεί απαραίτητα να χρησιμοποιήσει και factory

Δημοσ.

Παρειπηπτώντως(έτσι γράφεται;) αυτό το singleton είναι γνωστό και ως Meyers Singleton. Ντροπή και αίσχος όποιος δεν γνωρίζει τον Scott Meyers :-D :-D :-D

 

Ντροπή και αίσχος, να κρεμαστούν στο ίδιο δέντρο που κρεμάμε όσους δε γνωρίζουν τους Sutter και Alexandrescu :P

 

By the way ξέχασες κάτι (hint: "rule of three").

Δημοσ.

Y.Γ:ψάντωντας να βρώ τι ξέχασα(μεσημέρι είναι και πλέον δεν ασχολούμαστε με το άθλημα ενεργά πλέον) βρήκα ένα άρθρο σχετικά με singleton το οποίο είχε μια template υλοποίηση που πιθανόν να ενδιαφέρει τον topic starter.

 

Νομίζω ότι εδώ πρέπει να το πούμε ξεκάθαρα ότι με μια τέτοια υλοποίηση (που είναι γενικά καλή σαν ιδέα υλοποίησης, δεν το λέω σα μειονέκτημα) χρειάζεται πάλι συμφωνία κυρίων: το Singleton<Foo> είναι singleton, αλλά η Singleton<Foo>::Instance() επιστρέφει ένα Foo και τίποτα δεν εμποδίζει κάποιον να αρχίσει να φτιάχνει κι άλλα Foo μόνος του.

 

Οπότε σε μια τέτοια περίπτωση αντιμετωπίζουμε το Singleton<Foo> σαν "το Foo που θα θέλαμε να έχουμε" (κάνουμε κι ενα typedef για ευκολία αμα λάχει) και το ίδιο το Foo ξεχνάμε ότι υπάρχει. Σαν αντάλλαγμα γι' αυτό έχουμε αποκτήσει τη δυνατότητα να "βαφτίσουμε singleton" όποια class θέλουμε χωρίς κόπο.

 

Πάντως (ξαναγυρίζω σε κάτι που ανέφερα νωρίτερα) έτσι τελικά δεν καταφέραμε τίποτα καλύτερο απ' ότι αν είχαμε μια global μεταβλητή τύπου Foo -- απλά κάθε φορά που θέλουμε access χρειάζεται παραπάνω πληκτρολόγηση. Το οποίο δε σημαίνει ότι είναι κακή η συγκεκριμένη υλοποίηση, αλλά ότι είναι κακή ιδέα το singleton γενικότερα.

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...