new
बिल्डर बनाता है। आप वास्तव में निर्मित ऑब्जेक्ट को वापस करने के लिए कुछ अन्य विधि चाहते हैं।
class RepositoryBuilder {
has 'allow_network_repositories' => (
is => 'ro',
isa => 'Bool',
required => 1,
);
method build_repository(Uri $url) {
confess 'network access is not allowed'
if $url->is_network_url && !$self->allow_network_repositories;
my $class = $self->determine_class_for($url); # Repository::Whatever
return $class->new(url => $url);
}
}
role Repository { <whatever }
class Repository::File with Repository {}
class Repository::HTTP with Repository {}
यहाँ, बिल्डर और निर्मित वस्तु भिन्न हैं:
यहाँ एक उदाहरण है। बिल्डर असली ऑब्जेक्ट है, पैरामीटर के साथ पूर्ण है, जिसे स्थिति की मांग के रूप में ऑब्जेक्ट्स बनाने के लिए अनुकूलित किया जा सकता है। फिर, "निर्मित" ऑब्जेक्ट्स केवल एक विधि के मान लौटाते हैं। यह आपको स्थिति के आधार पर अन्य बिल्डर्स बनाने की अनुमति देता है। (बिल्डर फ़ंक्शंस के साथ एक समस्या यह है कि वे बहुत ही लचीले होते हैं - उन्हें एक नया विशेष मामला सिखाना मुश्किल है। यह समस्या अभी भी बिल्डर ऑब्जेक्ट, के साथ मौजूद है लेकिन कम से कम आपका एप्लिकेशन उप-वर्ग बना सकता है, इसे तुरंत चालू करें, और कुछ भी वस्तुओं को बनाने की जरूरत है कि यह वस्तु गुजरती हैं। लेकिन निर्भरता इंजेक्शन इस मामले में एक बेहतर तरीका है।)
इसके अलावा, वहाँ खजाने आप कुछ भी से प्राप्त करना निर्माण के लिए कोई जरूरत नहीं है, वे सिर्फ एक की जरूरत है टैग इंगित करता है कि वे भंडार हैं। और यही हमारी Repository
भूमिका है। (आप एपीआई कोड यहां जोड़ना चाहेंगे, और किसी भी तरीके का पुन: उपयोग किया जाना चाहिए।लेकिन सावधानी बरतने के बारे में सावधान रहें - क्या आप सुनिश्चित हैं कि के साथ टैग की गई सभी चीजें रिपोजिटरी भूमिका उस कोड को चाहेंगी? यदि नहीं, तो कोड को में एक और भूमिका दें और उस वर्ग को उस पर लागू करें जिसके लिए कार्यक्षमता की आवश्यकता है।)
यहां हम निर्माता द्वारा बनाए गए निर्माता का उपयोग करते हैं। हैं, कहते हैं, आप नहीं स्पर्श करने के लिए नेटवर्क हैं:
my $b = RepositoryBuilder->new(allow_network_repositories => 0);
$b->build_repository('http://google.com/'); # error
$b->build_repository('file:///home/whatever'); # returns a Repository::Foo
लेकिन अगर आप कार्य करें:
my $b = RepositoryBuilder->new(allow_network_repositories => 1);
$b->build_repository('http://google.com/'); # Repository::HTTP
अब आप एक बिल्डर है कि वस्तुओं को अपनी इच्छानुसार बनाता है, आपको बस इन ऑब्जेक्ट्स को अन्य कोड में उपयोग करने की आवश्यकता है। तो पहेली में अंतिम टुकड़ा अन्य कोड में "किसी भी प्रकार का रिपोजिटरी ऑब्जेक्ट" का जिक्र कर रहा है। यही कारण है कि आसान है, आप isa
के बजाय does
का उपयोग करें:
class SomethingThatHasARepository {
has 'repository' => (
is => 'ro',
does => 'Repository',
required => 1,
);
}
और बस हो गया।
mmh पर एक नोट जोड़ा ... मुझे इस भूमिका की बात समझने दो, मूस दस्तावेज़ों पर वापस ... इसके अलावा, मेरे बारे में मेरा पहला विचार, क्योंकि मैं बस मूस से शुरू करता हूं , क्या मूस –
@alex की तुलना में खराब मूस करना अभी भी बेहतर है या नहीं: यदि आप मूस :: मैनुअल :: * में उदाहरणों का पालन करते हैं, तो आप कठिनाई के बिना मूस की अधिकांश सुविधाओं का उपयोग कर सकते हैं। यह केवल तभी होता है जब आप 'मेटा' का उपयोग शुरू करते हैं कि चीजें पागल हो जाती हैं :) – Ether
ठीक है, समझ में आया, लेकिन मैं सूक्ष्म मतभेदों के बारे में उत्सुक हूं: ए) सभी मूल विशेषताओं के साथ एक मूस बेस क्लास 'रिपोजिटरी'; विशिष्ट मूस वर्ग 'रिपोजिटरी :: _ एसएफटीपी' जो "विस्तार"/आधार वर्ग विरासत में आता है; एक मूस (या नहीं) कारखाना 'रिपोजिटरीबिल्डर', मुझे विशेष वर्ग का एक उदाहरण बनाने के तरीके के साथ, जिसे 'रिपोजिटरी' के रूप में अज्ञात रूप से छेड़छाड़ की जा सकती है। बी) एक जैसा ही), लेकिन बेस क्लास की बजाय भूमिका के साथ <- जो आपने प्रस्तावित किया है, है ना? सी) और डी) मूसएक्स :: सार फैक्ट्री या मूसएक्स :: एबीसी, लेकिन ये डिफ़ॉल्ट रूप से उपलब्ध नहीं हैं (मैं रेफरी के लिए सेंटोस 5 लेता हूं) –