C Singleton deseni
Singleton deseni hakkında bir sorum var.
İki durumda singleton sınıfının statik üye ile ilgili gördüm.
İlk nesne, bu gibi
class CMySingleton
{
public:
static CMySingleton& Instance()
{
static CMySingleton singleton;
return singleton;
}
// Other non-static member functions
private:
CMySingleton() {} // Private constructor
~CMySingleton() {}
CMySingleton(const CMySingleton&); // Prevent copy-construction
CMySingleton& operator=(const CMySingleton&); // Prevent assignment
};
Bir işaretçi, gibi
class GlobalClass
{
int m_value;
static GlobalClass *s_instance;
GlobalClass(int v = 0)
{
m_value = v;
}
public:
int get_value()
{
return m_value;
}
void set_value(int v)
{
m_value = v;
}
static GlobalClass *instance()
{
if (!s_instance)
s_instance = new GlobalClass;
return s_instance;
}
};
İki dava arasındaki fark nedir? Hangisi doğru?
CEVAP
Muhtemelen Alexandrescu kitap okumalısın.
İlgili yerel statik görmedim Visual Studio için bir süre, ama ne zaman derleme ile Visual Studio 2003, ' bir yerel statik tahsis başına DLL... konuşmak hakkında bir kabus hata ayıklama bunu unutmam için bir süre :/
1. Bir Tek ömür boyu
Tekiz ile ilgili temel sorun, ömür boyu yönetimidir.
Eğer hiç bir nesne kullanmayı deneyin, canlı ve hareketli olmak gerekir. Sorun böylece bütünsel C ile ortak bir sorun olan başlatma ve imha.
Başlatma genellikle düzeltmek için en kolay şeydir. Her iki yöntem de önerdiği gibi, ilk kullanımda başlatmak için yeteri kadar basit.
Bu yıkım biraz daha hassas. genel değişkenler oluşturulduğu ters sırada yok. Yerel statik durumda, aslında her şeyi kontrol edemezsin...yani.
2. Yerel bir statik
struct A
{
A() { B::Instance(); C::Instance().call(); }
};
struct B
{
~B() { C::Instance().call(); }
static B& Instance() { static B MI; return MI; }
};
struct C
{
static C& Instance() { static C MI; return MI; }
void call() {}
};
A globalA;
Burada sorun nedir ? Yani kurucular ve yıkıcılar olarak sipariş bakalım.
İlk olarak, inşaat aşamasında:
A globalA;
yürütülürA::A()
B::B()
çağırırA::A()
C::C()
çağırır
B
C
ilk giriş örneklerini biz başlatılamıyor, çünkü gayet iyi çalışıyor.
İkincisi, yıkım aşaması
C::~C()
son 3 inşa edilmiştir, çünkü denirB::~B()
adlı... oops, 19**'örneği ! erişmeye çalışır.
Biz böylece yıkım, hum, tanımsız davranış
3. Yeni strateji
Buradaki fikir basit. built-ins işaretçiyi yazdığınız kodun herhangi bir adlı önce 0
set olacak diğer bütünsel önce başlatılan, küresel, test sağlar:
S& S::Instance() { if (MInstance == 0) MInstance = new S(); return *MInstance; }
Ya bu örneği doğru olup olmadığını kontrol eder aslında.
Ancak, orada bir bellek sızıntısı burada ve en kötü söylenmiş asla çağrılan bir yıkıcı. Çözüm var, ve standart. atexit
işlev çağrısı.
atexit
fonksiyon yürütmek için bir eylem belirtin program kapatma sırasında izin ver. Bu, tek bir iyi yazabiliriz:
// in s.hpp
class S
{
public:
static S& Instance(); // already defined
private:
static void CleanUp();
S(); // later, because that's where the work takes place
~S() { /* anything ? */ }
// not copyable
S(S const&);
S& operator=(S const&);
static S* MInstance;
};
// in s.cpp
S* S::MInstance = 0;
S::S() { atexit(&CleanUp); }
S::CleanUp() { delete MInstance; MInstance = 0; } // Note the = 0 bit!!!
İlk olarak, daha fazla atexit
hakkında bilgi edinin. İmza argüman olarak bir şey alır bir işlev için bir işaretçi kabul eder ve hiçbir şey döndürür int atexit(void (*function)(void));
ıe.
Nasıl çalışır ? Bir işlev işaretçisi yığın aramak kurar ve imha sırasında bir kerede tek bir öğe yığını dökülür de başlatma. tam olarak önceki kullanım örneği: Bu durumda, bu fonksiyon Son-İlk-bir şekilde aradı.
İşte o zaman ne olur ?
İlk erişim (başlatma ince) inşaat, çıkış zamanı
CleanUp
yöntemi kayıt olurumÇıkış süresi:
CleanUp
yöntemi çağrılır. Nesne (böylece etkili bir yıkıcı iş yapabiliriz) yok eder ve0
işaretçiyi sıfırlama sinyali için.
Çoktan yok olmuş bir nesne örneği çağırıyorum (A
, B
C
ile örnekte olduğu gibi) ne olur ? Geri 0
işaretçiyi kurduğumdan beri bu durumda, geçici bir singleton yeniden yapacağım ve yeni bir döngü başlıyor. Benim yığını depiling olduğum için uzun ama canlı değil.
Alexandrescu ile yok oldu sonra ihtiyaç halinde kendi küllerinden diriltiyor olarak Phoenix Singleton
denir.
Başka bir seçenek var statik bir bayrak ve ayarlamak için destroyed
sırasında temiz ve kullanıcı bilmediği bir örneğinin singleton, örneğin tarafından dönen bir boş gösterici. Bir işaretçi (referans) dönen, tek sorun daha iyi kimse: / delete
Ara kadar aptal olmalısın
4. Monoid Desen
Singleton
bahsederken Monoid
Desen tanıtmanın zamanı geldi sanırım. Özünde, Flyweight
desen, veya Singleton
Proxy
bir kullanım dejenere bir durum olarak görülebilir.
Basit Monoid
desen: sınıf payı tüm örneklerini sık karşılaşılan bir durum.
-Phoenix uygulanmasını göstermek için bu fırsatı:) ederim
class Monoid
{
public:
void foo() { if (State* i = Instance()) i->foo(); }
void bar() { if (State* i = Instance()) i->bar(); }
private:
struct State {};
static State* Instance();
static void CleanUp();
static bool MDestroyed;
static State* MInstance;
};
// .cpp
bool Monoid::MDestroyed = false;
State* Monoid::MInstance = 0;
State* Monoid::Instance()
{
if (!MDestroyed && !MInstance)
{
MInstance = new State();
atexit(&CleanUp);
}
return MInstance;
}
void Monoid::CleanUp()
{
delete MInstance;
MInstance = 0;
MDestroyed = true;
}
Peki ne yararı var ? Gizler devlet paylaştırılmış olması, Singleton
gizler.
- Eğer hiç gerek yok 2 ayrı devletler, mümkün olduğunu göreceksiniz yönetmek olmadan değişen her satır kod kullanılır (değiştirme
Singleton
bir araFactory
örneğin) - Nodoby senin singleton
delete
örnek arayacak, gerçekten devleti yönetmek ve kazaları önlemek yani... çok kötü niyetli kullanıcılara karşı yine de yapamazsın! - Tekil erişim kontrol, yok oldu sonra deniyor diye doğru bir şey yapmak, günlük, vb...) işleyebilir
5. Son bir söz
Bu görünse de tam, mutlu bir şekilde daha fazla bilgi edinmek için herhangi bir çoklu sorunları... read Alexandrescu Modern C yağsız olduğumu belirtmek isterim!
Singleton Deseni ile ilgili sorunlar...
PHP5 içinde Singleton tasarım deseni o...
Java singleton deseni uygulamak için e...
SQLiteDatabase için kullanarak Singlet...
C Singleton deseni ...