2010-06-17 9 views
5

मैं पर्ल और मूस का उपयोग करके सिंगलटन भूमिका लिखने का प्रयास कर रहा हूं। मैं समझता हूं कि एक MooseX :: सिंगलटन मॉड्यूल उपलब्ध है लेकिन हमारे प्रोजेक्ट के लिए एक और सीपीएएन मॉड्यूल की आवश्यकता होने पर हमेशा प्रतिरोध होता है। इसे करने के बाद और थोड़ा परेशानी होने के बाद मैं समझना चाहूंगा कि मेरी विधि क्यों काम नहीं कर रही है। मैंने लिखा सिंगलटन भूमिका निम्नानुसार है:मूस में सिंगलटन भूमिकाएं

package Singleton; 
use Moose::Role; 

my $_singleInstance; 

around 'new' => sub { 
    my $orig = shift; 
    my $class = shift; 
    if (not defined $_singleInstance){ 
     $_singleInstance = $class->$orig(@_); 
    } 
    return $_singleInstance; 
}; 

sub getInstance 
{ 
    return __PACKAGE__->new(); 
} 

1; 

ऐसा लगता है कि केवल एक वर्ग सिंगलटन भूमिका का उपयोग करता है। हालांकि, जब दो कक्षाएं (उदाहरण के लिए कक्षाए और कक्षा बी) दोनों सिंगलटन भूमिका का उपभोग करते हैं, तो ऐसा लगता है कि वे दोनों साझा $ _singleInstance चर का जिक्र कर रहे हैं। अगर मैं क्लास-> getInstance को कॉल करता हूं तो यह क्लास ए ऑब्जेक्ट का संदर्भ देता है। अगर मैं क्लासबी-> कुछ समय बाद उसी स्क्रिप्ट में प्राप्त करता हूं तो यह क्लासए के किसी ऑब्जेक्ट का संदर्भ देता है (भले ही मैंने कक्षा बी के लिए getInstance विधि को स्पष्ट रूप से कहा)। अगर मैं भूमिका का उपयोग नहीं करता हूं और वास्तव में सिंगलटन भूमिका से क्लास ए और क्लासबी में कोड कॉपी और पेस्ट करता हूं तो यह ठीक काम करता प्रतीत होता है। यहाँ क्या चल रहा है?

+1

आपको एहसास है कि 'नया' लपेटना सिर्फ चोट की दुनिया के लिए पूछ रहा है, है ना? – Ether

उत्तर

3

आप प्रत्येक वर्ग प्रकार के लिए अलग-अलग उपयोग करने के बजाय सभी प्रकार के उदाहरण को सहेज रहे हैं।

इस फैक्टरी डिजाइन पैटर्न के लिए कहता है, जैसे:

package MyApp::Factory; 

my %instances; 

# intantiates an object instance if there is none available, 
# otherwise returns an existing one. 
sub instance 
{ 
    my ($class, $type, @options) = @_; 

    return $instances{$type} if $instances{$type}; 
    $instances{$type} = $type->new(@options); 
} 

तुम सच में एकमात्र चाहते हैं, MooseX :: सिंगलटन स्थापित करें बल्कि अपने खुद के रोलिंग से - अगर आप स्रोत को देखो आप देखेंगे यह बहुत बढ़िया मामलों के लिए जिम्मेदार है। हालांकि, मैं आपके वर्गों को सिंगलेट होने के लिए मजबूर करने की सलाह दूंगा, क्योंकि इससे कक्षा से नियंत्रण दूर हो जाता है। इसके बजाए, एक फैक्ट्री (ऊपर के रूप में) का उपयोग करें, इसलिए कॉलर सभी उपभोक्ताओं को एक उपयोगकेस में मजबूर करने के बजाए कक्षा का निर्माण कैसे कर सकता है।

1

वे आवृत्ति चर साझा कर रहे हैं। आपको भूमिका का उपयोग करके पैकेज के अंदर आवंटित करने की आवश्यकता है।

# find storage for instance 
my $iref = \${ "${class}::_instance" }; 

# an instance already exists; return it instead of creating a new one 
return $$iref if defined $$iref; 

# no instance yet, create a new one 
... 
+2

यदि आप उस मार्ग पर जा रहे हैं, तो मेटाक्लास भूमिका का उपयोग करके प्रतीक तालिका के साथ बंदर की तुलना में शायद बहुत अधिक मजबूत है। – friedo

3

आपका $_singleInstance lexically जहां यह प्रतीत होता है, इस मामले में अपने पूरे Singleton पैकेज में ब्लॉक के दायरे वाला। आपका around संशोधक इस चर पर एक बंदरगाह बनाता है, जिसका अर्थ है कि यह समान$_singleInstance हर बार चलाया जाता है, भले ही यह किस वर्ग में बनता है।

हल करने के लिए इस हैश पर अपने एकमात्र स्टोर करने के लिए किया जाएगा एक आसान तरीका:

my %_instances; 

around 'new' => sub { 
    my $orig = shift; 
    my $class = shift; 
    if (not defined $_instances{$class}){ 
     $_instances{$class} = $class->$orig(@_); 
    } 
    return $_instances{$class}; 
}; 

शायद एक बेहतर तरीका एक कस्टम metaclass भूमिका है कि प्रत्येक वर्ग है कि खपत के लिए सिंगलटन उदाहरण संग्रहीत करता है स्थापित करने के लिए किया जाएगा वह भूमिका।

+0

मुझे लगा कि यह एक मुद्दा था जिसमें परिवर्तनीय भूमिका निभाई जा रही थी।यह थोड़ा उलझन में था क्योंकि __PACKAGE__ भूमिका का उपभोग करने वाले पैकेज को संदर्भित करता है, न कि "Sngleton" पैकेज/भूमिका। मैंने आशा की थी कि किसी भूमिका में परिभाषित किए गए किसी भी चर को पैकेज का पैकेज किया जाएगा, न कि भूमिका का पैकेज। – mjn12

+1

मूस पर्ल पार्स के तरीके को प्रभावित करता है या चर को समझता है। जिस व्यवहार को आप यहां काम कर रहे हैं, उसे बनाने के लिए कोई (आसान) तरीका नहीं है, और पूरी तरह से मूस के दायरे से परे होगा। – perigrin

2

"मैं समझता हूँ एक MooseX :: सिंगलटन मॉड्यूल उपलब्ध है, लेकिन वहाँ हमेशा प्रतिरोध है जब हमारे परियोजना के लिए एक और CPAN मॉड्यूल की आवश्यकता होती है।"

यह वास्तव में कुछ संबोधित करने की जरूरत है। एक डिप्टी के रूप में, एमएक्स: सिंगलटन बहुत छोटा है। मामला क्या है? क्या आप किसी साझा सर्वर या इसी तरह वैश्विक स्तर पर साझा पर्ल पर फंस गए हैं? यदि ऐसा है, तो आपको वास्तव में स्थानीय :: lib को देखना चाहिए, जिसे व्यक्तिगत डेवलपर्स के लिए किसी भी अन्य CPAN मॉड्यूल की तरह, Makefile.PL स्क्रिप्ट के साथ सीपीएएन निर्भरताओं को ठीक से प्रबंधित करने के लिए डिज़ाइन किया गया है।

+1

प्रश्न का उत्तर देने के लिए समय निकालने के लिए धन्यवाद, हालांकि यह वास्तव में सहायक नहीं है। मैंने यह समझने में मदद मांगी कि यह विशेष कोड क्यों काम नहीं कर रहा था और इस तरह की प्रतिक्रिया से बचने के लिए MooseX :: सिंगलटन के अस्तित्व को स्वीकार किया। – mjn12

संबंधित मुद्दे