2009-08-07 12 views
11

क्या आने वाले डेटा के आधार पर कक्षाओं को तुरंत चालू करने के लिए पर्ल और Moose का उपयोग करने के लिए एक सरल या बेहतर (= > आसान बनाए रखने का तरीका) है?मैं पर्ल और मूस में एक कारखाने को कैसे कोड कर सकता हूं?

निम्न कोड एक प्रोजेक्ट से एक अलग नमूना है जिसे मैं काम कर रहा हूं।

package FooBar; 
use Moose; 
has 'SUBCLASS' =>('isa'=>'Str',required=>'1',is=>'ro'); 
has 'MSG' =>('isa'=>'Str',required=>'1',is=>'ro'); 

sub BUILD { 
     my $self = shift; 
     my ($a)[email protected]_; 
     bless($self,$a->{SUBCLASS}) 
} 
sub Hi { 
    my $self=shift; 
    print "Hi, I'm a " . ref($self) ." and I say [". $self->MSG()."]\n"; 
} 

package Foo; 
use Moose; 
extends ("FooBar"); 

package Bar; 
use Moose; 
extends ("FooBar"); 

package main; 
use strict; 
use warnings; 

for my $line (<DATA>) { 
    my ($case,$msg)=split(/[\n\r,]\s*/,$line); 
    FooBar->new(SUBCLASS=>$case,MSG=>$msg)->Hi(); 
} 

__DATA__ 
Foo, First Case 
Bar, Second Case 

संपादित: यह सिर्फ मुझे लगा कि यह बहुत ज्यादा क्या होता है जब आप DBI कहते हैं। यदि यह आसान या बेहतर है

$case->new(MSG => $msg)->Hi(); 

आप पर निर्भर तय करने के लिए है: पैरामीटर पारित आधार पर, यह है, जबकि एक (अधिकतर) संगत इंटरफेस

उत्तर

10

आईक। स्टीवन का एक बहुत ही आकर्षक तर्क है कि new हमेशा कक्षा का एक उदाहरण लौटा देना चाहिए। कुछ भी सिस्टम सीखने वाले नए लोगों को भ्रमित कर रहा है।

आप MooseX::AbstractFactory पर एक नज़र डालना चाहते हैं। है कि आप के लिए तो काम नहीं करेगा:

package FooBar; 
use Moose; 

has [qw(SUBCLASS MSG)] => (is => 'ro', required => 1); 

sub create_instance { 
    return $self->package->new(message => $self->msg); 
} 

package FooBar::Object; 
use Moose; 

has msg => (is => 'ro', required => 1); 

sub Hi { 
    my $self = shift; 
    print "Hi, I'm a " . ref($self) ." and I say [". $self->MSG()."]\n"; 
} 

package Foo; 
use Moose; 
extends qw(FooBar::Object); 

package Bar; 
use Moose; 
extends qw(FooBar::Object); 


package main; 
or my $line (<DATA>) { 
    my ($case,$msg)=split(/[\n\r,]\s*/,$line); 
    FooBar->new(SUBCLASS=>$case,MSG=>$msg)->create_instance->Hi 
} 

__DATA__ 
Foo, First Case 
Bar, Second Case 

बेशक वहाँ मूस में यह इसी अवधारणा को लागू करने के कई अन्य तरीके हैं। आपके डोमेन समस्या की बारीकियों को जानने के बिना यह बताने के लिए MooseX::Traits की तरह है कि कुछ बेहतर नहीं होगा मुश्किल है:

package Foo; 
use Moose; 
with qw(MooseX::Traits); 

package Bar; 
use Moose; 
with qw(MooseX::Traits); 

package Messaging; 
use Moose::Role; 

has msg => (is => 'ro', required => 1); 

sub Hi { 
    my $self = shift; 
    print "Hi, I'm a " . ref($self) ." and I say [". $self->MSG()."]\n"; 
} 

package main; 
use strict; 
Foo->with_traits('Messaging')->new(msg => 'First Case')->Hi; 

यह मोटे तौर पर है अन्य पोस्टर एक भूमिका आधारित समाधान का उपयोग कर के बारे में क्या मतलब है।

+0

धन्यवाद, मुझे ग्रोक करने में कुछ समय लगेगा :-) – lexu

+1

** में [qw (सबस्क्लस एमएसजी)] => है => 'ro', आवश्यक => 1); ** साफ चाल .. लेकिन "अनजान" किसी के लिए perl से परिचित नहीं है .. – lexu

+0

नहीं यह नहीं है। यह मूस एपीआई का हिस्सा है और पर्ल के साथ कुछ लेना देना नहीं है। (यदि आप अनजान होना चाहते हैं, तो आप लिखेंगे "qw/SUBCLASS MSG /" के लिए $ _ => (...) है। लेकिन निश्चित रूप से, हर कोई जानता है कि यह भी क्या करता है।) – jrockway

5

आप बस कर सकता है बनाए रखने के पूरी तरह से अलग कोड का प्रयोग करेंगे।

+0

कक्षा के रूप में एक परिवर्तनीय का उपयोग कर तत्काल ** $ case-> नया (..) ** इस तरह से बहुत अजीब लगता है। लेकिन हाँ, बेहद कॉम्पैक्ट, जब मेरे कोड की तुलना में (जहां मैं इसे वर्तनी करता हूं ** ** आशीर्वाद ({}, $ केस) ** टिप के लिए धन्यवाद! – lexu

+1

यह अजीब क्यों है? पर्ल में एक वर्ग का नाम सिर्फ एक है स्ट्रिंग। फू-> ब्लाह बिल्कुल "फू" -> ब्लाह जैसा है। –

+1

यदि कारखाने में तत्काल उपक्रम चुनने के लिए कारखाने में कोई तर्क नहीं है तो यह अधिक कारखाना नहीं है और यह व्यापक मार्जिन द्वारा सबसे अच्छा समाधान है – Schwern

4

ठीक है, वस्तु पहले से ही बनाई गई है जब BUILD कहा जाता है, तो मैं कहूंगा कि

sub BUILD { 
     my $self = shift; 
     return bless $self, $self->SUBCLASS; 
} 

तुम हमेशा एक विरासत आधारित मॉडल से एक भूमिका आधारित मॉडल जहां वस्तु आप चाहते बनाने के लिए स्विच करने के लिए इच्छा हो सकती है (कारखाने वर्ग में कक्षा पारित करने के बजाय), फिर आम भूमिका लागू करें।

+0

कहां क्या आप मुझे "विरासत आधारित" के "भूमिका आधारित" के संक्रमण को सीखने/समझने के लिए भेज देंगे? – lexu

+3

भूमिकाओं पर मूस मैनुअल एक प्रारंभ होगा http://search.cpan.org/perldoc/Moose:: मैनुअल :: रोल –

+0

@Sinan Ünür: उस लिंक के लिए धन्यवाद! – lexu

5
जवाब में से कुछ पर

बस एक ध्यान दें:

निर्माण में bless कॉलिंग, या कहीं भी एमओपी internals के बाहर, हमेशा अस्वीकार्य है। (यदि आपको अव्यवस्थित होना चाहिए, तो Class::MOP::Class->rebless_instance है!)

को __PACKAGE__ के उदाहरण के अलावा कुछ भी वापस करने की अनुमति देने की सलाह देने के लिए दूसरी सलाह नहीं है। यदि आप ऐसी विधि चाहते हैं जो किसी चीज़ का उदाहरण बनाता है, तो इसे और कुछ कहें।उदाहरण:

class Message { 
    method new_from_string(Str $msg){ 
     my ($foo, $bar, $baz) = ($msg =~ /<...>/); # blah blah blah 
     my $class = "Message::${foo}::$baz"; 
     Class::MOP::load_class($class); 
     return $class->new(bar => $msg); 
    } 
} 

उसके बाद, आप एक शाब्दिक संदेश बनाने के लिए चाहते हैं जब:

Message->new(whatever => 'you want'); 

आप एक स्ट्रिंग पार्स और सही संदेश उपवर्ग वापसी करना चाहते हैं:

Message->new_from_string('OH::Hello!'); 

अंत में, अगर संदेश का उदाहरण बनाने में सक्षम होने के लिए यह समझ में नहीं आता है, तो यह कक्षा नहीं होनी चाहिए। यह एक भूमिका होनी चाहिए।

आप निश्चित रूप से किसी अन्य वस्तु के साथ इमारत को संभाल सकते हैं। बस केवल स्ट्रिंग प्रारूप को समझने, उदाहरण के लिए के लिए यकीन है कि यह अन्य वस्तु जिम्मेदार है, और नहीं संदेश internals:

class MessageString { 
    has 'string' => (initarg => 'string', reader => 'message_as_string'); 

    method new_from_string(ClassName $class: Str $string) { 
     return $class->new(string => $string); 
    } 

    method as_message_object { 
     # <parse> 
     return Message::Type->new(params => 'go here', ...); 
    } 
} 

role Message { ... } 
class Message::Type with Message { ... } 
अब आप नहीं रह गया है कुछ "सुपर-क्लास" होने को लेकर चिंतित हैं, "उपवर्गों" के निर्माण के लिए जिम्मेदार

जो मुझे लगता है कि बेहतर डिजाइन है। (याद रखें, MessageString कक्षाओं कर उस पर "संदेश" कोई विशेष शक्ति है कि कुंजी यहाँ है, यह stringified संदेशों को समझने के लिए केवल जिम्मेदार है।।)

वैसे भी, अब तुम सिर्फ:

my $data = <>; # Yup, I called it $data. Sorry, Andy Lester. 
my $parsed = MessageString->new_from_string($data); 
my $message = $parsed->as_message_object; 
$message->interact_with 

(आप "एमवीसी" जानते हैं? यह समान है।)

3

बस उस वर्ग की वस्तुओं को बनाने के लिए एक और कारखाने वस्तु का उपयोग करें।

, सरल और अधिक लचीला और अधिक विश्वसनीय, आदि

my $factory = Factory->new(... factory parameters ...);

my $object = $factory->new_object(... various parameters ...);

new_object पैरामीटर पार्स और $factory और उन मानकों से डेटा के अंदर दोनों डेटा पर निर्णय कर सकते हैं जहां।

जब आप समझते हैं कि आपको अगले चरण में कोडपेन्डेंट ऑब्जेक्ट्स की आवश्यकता होगी, तो नियंत्रण ढांचे के उलटाई की तलाश करें।

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