की नई सुविधाओं का उपयोग करके डेल्फी में एक सिंगलटन बनाना मैं डेल्फी में एक सिंगलटन बनाना चाहता हूं। मैंने डेल्फी के पुराने संस्करणों का उपयोग करने से पहले ऐसा किया है, और वैश्विक चर (कार्यान्वयन अनुभाग में) का उपयोग करके और उदाहरण की देखभाल करने के लिए प्रारंभिकरण और अंतिमकरण का उपयोग करके समाप्त कर दिया है। इसके अलावा उपयोगकर्ता को एक उदाहरण बनाने से रोकने का कोई तरीका नहीं था क्योंकि आप मानक कन्स्ट्रक्टर को छुपा नहीं सकते थे। मैं सोच रहा था कि क्लास कन्स्ट्रक्टर और विनाशक, और कक्षा चर (ठीक है, इतना नया नहीं), शायद जेनेरिक, जेनेरिक सिंगलटन क्लास बनाने में मदद कर सकता है। मैंने अभी तक अपनी संतुष्टि के लिए कुछ नहीं बनाया है।डी 2009 और डी 2010
उत्तर
यह डेल्फी में सही संभाजक और deallocator तरीकों, NewInstance और FreeInstance अधिभावी द्वारा इस का प्रबंधन करने के लिए संभव था।डेल्फी में रचनाकार और विनाशक क्रमशः प्रारंभ और अंतिम रूप देते हैं, वे स्मृति आवंटित या आवंटित नहीं करते हैं, इसलिए रचनाकारों को छिपाने का प्रयास हमेशा थोड़ा गुमराह होता था।
यानी न्यूइन्स्टेंस जैसे ओवरडोड होने पर, किसी भी और सभी रचनाकारों के निःशुल्क उपयोग की अनुमति देना संभव था, जैसे कि यह कक्षा के लिए स्मृति के एक एकल आवंटन के संदर्भ में कभी भी वापस लौटा।
लेकिन बेस क्लास में उपयोग/व्यवहार पैटर्न को लागू करने का प्रयास करना एक गलती है Iho। पैटर्न को समाहित करने के लिए सभी पैटर्न नहीं हैं या विशिष्ट वर्गों की आवश्यकता नहीं है।
इस तरह के मामलों में आप कुछ ऐसी चीज तैयार करते हैं जो अनिवार्य रूप से जटिल है, और जटिलता मेरे अनुभव में त्रुटियों को आकर्षित करती है और अभ्यास की वस्तु पैटर्न पैटर्न कार्यान्वयन में त्रुटियों को खोजने की कोशिश कर रही है और फिर उन लोगों के खिलाफ सुरक्षा उपाय करने की कोशिश कर रही है काम के व्यावहारिक काम के साथ मिलकर त्रुटियों की बजाय, सिंगलटन वर्ग को प्रदर्शन करना था।
यह दूर है, कक्षा के यूएसएजी दस्तावेज़ को दस्तावेज करने के लिए एफएआर सरल और अधिक प्रभावी है। इस पद्धति को लागू करने के लिए एक तकनीक के रूप में
प्रलेखन आवेदन और स्क्रीन VCL में वस्तुओं के लिए 15 साल के लिए दोषरहित काम किया है, उदाहरण के लिए, अनगिनत अन्य एकमात्र कि मैं उन वर्षों में बना लिया है उल्लेख करने के लिए नहीं।
एक सिंगलटन के लिए, आप न्यूइन्स्टेंस विधि को ओवरराइड कर सकते हैं। और एक वर्ग चर का उपयोग करें। आप पहले कॉल पर चर बनाते हैं और पॉइंटर को कक्षा में एक दूसरे को कॉल करते हैं।
आपको अंत में इसे नष्ट करने के लिए कभी-कभी कुछ खोजने की आवश्यकता है (शायद अंतिम रूप का उपयोग करके)।
डेल्फी 2010 में अब तक का सबसे अच्छा और सुरक्षित तरीका वर्ग निर्माता का उपयोग करना है। here देखें - विशेष रूप से नामक अनुच्छेद पढ़ें बेहतर encapsulation।
एचटीएच।
यह एक शर्म की बात है कि उन्होंने इस सुविधा को सही तरीके से दस्तावेज करने के लिए परेशान नहीं किया है, या इसे सहायता में "व्हाट्स न्यू" में शामिल किया है। सिंगलटन पर इटालिक भाग के लिए – IanH
मैं इंटरफेस का उपयोग करना पसंद करता हूं जब मुझे सिंगलेट की आवश्यकता होती है और कार्यान्वयन अनुभाग में इंटरफ़ेस के कार्यान्वयन को छुपाया जाता है।
- स्वत: विनाश लाभ जब कार्यक्रम समाप्त हो जाता है।
- दुर्घटनाग्रस्त रूप से एक TMySingleton बनाने का कोई तरीका नहीं है।
कमियां
- किसी ने अपने आप ही IMySingleton लागू करने के लिए तय कर सकते हैं।
नोट: मुझे विश्वास है कि सिंगलेट्स के उपयोग को पूर्ण न्यूनतम रखा जाना चाहिए। सब कुछ, सिंगलेट्स गौरवशाली वैश्विक चर से थोड़ा अधिक हैं। यदि और जब आप अपने कोड का परीक्षण इकाई शुरू करते हैं, तो वे एक उपद्रव बन जाते हैं।
unit uSingleton;
interface
type
ISingleton = interface
['{8A449E4B-DEF9-400E-9C21-93DFA2D5F662}']
end;
function Singleton: ISingleton;
implementation
uses
SyncObjs;
type
TSingleton = class(TInterfacedObject, ISingleton);
var
Lock: TCriticalSection;
function Singleton: ISingleton;
const
_singleton: ISingleton = nil;
begin
if not Assigned(_singleton) then
begin
Lock.Acquire;
try
if not Assigned(_singleton) then
_singleton := TSingleton.Create();
finally
Lock.Release;
end;
end;
Result := _singleton;
end;
initialization
Lock := TCriticalSection.Create;
finalization
Lock.Free;
end.
+1। – mghie
@ मिगी: आप पैटर्न के कार्यान्वयन पर असहमत हैं? –
मैं आपसे सहमत हूं कि सिंगलटन पैटर्न के अधिकांश उपयोग वैश्विक चर की तुलना में कोई प्रगति नहीं हैं। लेकिन अगर कोई उन्हें (किसी भी कारण से) चाहता है, तो एक थ्रेड-सुरक्षित जेनेरिक समाधान आवश्यक होगा। आपका निश्चित रूप से नहीं है, इसलिए आप वास्तव में एक से अधिक उदाहरणों के साथ समाप्त हो सकते हैं। कम से कम यह स्मृति को रिसाव नहीं करता है, जो मैंने बड़े वाणिज्यिक पुस्तकालयों में देखा है, जहां इंटरफेस के बजाय सिंगलटन कार्यान्वयन के लिए वस्तुओं का उपयोग किया जाता है। मोरित्ज़ का समाधान ऐसा लगता है कि यह थ्रेड-सुरक्षित हो सकता है, लेकिन इसे पूरी तरह से जांचना होगा। – mghie
तुम सिर्फ एक सादे सिंगलटन की जरूरत है, सबसे आसान तरीका के रूप में plainth ने सुझाव दिया वर्ग निर्माणकर्ता और वर्ग तरीकों का उपयोग करने के लिए है। लेकिन जेनिक्स बहुत मददगार हैं यदि आपको मांग पर निर्माण के साथ सिंगलेट की आवश्यकता है (यानी पहली पहुंच पर)।
निम्नलिखित कोड मेरी उपयोगिता इकाइयों में से एक से लिया गया है; यह मूल रूप से डेल्फी 200 9 के लिए एक सामान्य सिंगलटन कारखाना प्रदान करता है।
interface
type
{$HINTS OFF}
{ TSingletonInstance<> implements lazy creation, which is sometimes useful for avoiding
expensive initialization operations.
If you do not require lazy creation and you target only Delphi 2010 onwards, you should
use class constructors and class destructors instead to implement singletons. }
TSingletonInstance<T: class, constructor> = record
private
FGuard: IInterface;
FInstance: T;
function GetInstance: T;
function CreateInstance: TObject;
public
property Instance: T read GetInstance;
end;
{$HINTS ON}
TSingletonFactoryFunction = function: TObject of object;
{ Private symbols (which are in the interface section because of known limitations of generics) }
procedure _AllocateSingletonInstance (InstanceRecord: Pointer; Factory: TSingletonFactoryFunction);
implementation
{ TSingleton }
var
SingletonCriticalSection: TRTLCriticalSection;
type
TSingletonGuard = class (TInterfacedObject)
private
FSingletonInstance: TObject;
public
constructor Create (AInstance: TObject);
destructor Destroy; override;
end;
PUntypedSingletonInstance = ^TUntypedSingletonInstance;
TUntypedSingletonInstance = record
FGuard: IInterface;
FInstance: TObject;
end;
// TODO: is a lock required for multiple threads accessing a single interface variable?
procedure _AllocateSingletonInstance (InstanceRecord: Pointer; Factory: TSingletonFactoryFunction);
var
USI: PUntypedSingletonInstance;
begin
USI := PUntypedSingletonInstance (InstanceRecord);
EnterCriticalSection (SingletonCriticalSection);
if USI.FInstance = nil then
begin
USI.FInstance := Factory();
USI.FGuard := TSingletonGuard.Create (USI.FInstance);
end;
LeaveCriticalSection (SingletonCriticalSection);
end;
constructor TSingletonGuard.Create (AInstance: TObject);
begin
FSingletonInstance := AInstance;
end;
destructor TSingletonGuard.Destroy;
begin
FSingletonInstance.Free;
inherited;
end;
function TSingletonInstance<T>.GetInstance: T;
var
Factory: TSingletonFactoryFunction;
begin
if FInstance = nil then
begin
Factory := Self.CreateInstance; // TODO: associate QC report
_AllocateSingletonInstance (@Self, Factory);
end;
Result := FInstance;
end;
function TSingletonInstance<T>.CreateInstance: TObject;
begin
Result := T.Create;
end;
initialization
InitializeCriticalSection (SingletonCriticalSection);
finalization
DeleteCriticalSection (SingletonCriticalSection);
प्रयोग इस प्रकार है:
type
TMySingleton = class
public
constructor Create;
class function Get: TMySingleton; static;
end;
var
MySingletonInstance: TSingletonInstance<TMySingleton>;
class function TMySingleton.Get: TMySingleton;
begin
Result := MySingletonInstance.Instance;
end;
ग्रेट कोड मोरित्ज़। –
धन्यवाद। वास्तव में यह सुंदर होगा अगर मैं डी 200 9 के लिए वर्कअराउंड हटा सकता हूं :) –
मैं कोड जनरेटर का उपयोग करके सिंगलटन क्लास बनाना पसंद करता हूं। सामान्य के साथ समस्या यह है कि, सभी कोड स्मृति में उत्पन्न होता है, स्रोत फ़ाइल में नहीं। यह डीबगिंग की कठिनाई में वृद्धि करेगा।
TObject के विरासत "बनाएं" कन्स्ट्रक्टर को छिपाने का एक तरीका है। यद्यपि पहुंच स्तर को बदलना संभव नहीं है, लेकिन इसे उसी नाम से अन्य सार्वजनिक पैरामीटर रहित विधि से छिपाया जा सकता है: "बनाएं"। यह सिंगलटन वर्ग के कार्यान्वयन को काफी सरल बनाता है। कोड की सादगी देखें:
unit Singleton;
interface
type
TSingleton = class
private
class var _instance: TSingleton;
public
//Global point of access to the unique instance
class function Create: TSingleton;
destructor Destroy; override;
end;
implementation
{ TSingleton }
class function TSingleton.Create: TSingleton;
begin
if (_instance = nil) then
_instance:= inherited Create as Self;
result:= _instance;
end;
destructor TSingleton.Destroy;
begin
_instance:= nil;
inherited;
end;
end.
मैं अपने मूल पोस्ट करने के लिए विवरण कहा: http://www.yanniel.info/2010/10/singleton-pattern-delphi.html
- 1. डी 2009 +
- 2. मेरा डी 2009 exennnnn.DAT
- 3. डी 2009 टीस्ट्रिंगलिस्ट उत्तर
- 4. ज़ेंड_Mail और = 0 डी = 0 ए = 3 डी = 3 डी = 3 डी = 3 डी = 3 डी
- 5. डी 2: डी साइड
- 6. डी
- 7. डी
- 8. डी
- 9. डी
- 10. डी
- 11. डी
- 12. डी
- 13. डी
- 14. डी
- 15. डी
- 16. डी
- 17. डी
- 18. डी
- 19. डी
- 20. डी
- 21. डी
- 22. डी
- 23. डी
- 24. डी
- 25. डी
- 26. डी
- 27. डी
- 28. डी
- 29. डी
- 30. डी
या D2010 में एक वर्ग नाशक। –