2011-03-30 17 views
7

से बचने की कोशिश कर रहा हूं, मैं अपने सिस्टम के लिए कारखाने के वर्गों का एक सेट तैयार करने की कोशिश कर रहा हूं, जहां कारखाने द्वारा बनाई गई कुछ वस्तुओं को भी ठीक से उपयोग करने से पहले प्रारंभ करने की आवश्यकता है।ऑब्जेक्ट प्रारंभिकता के साथ फैक्ट्री क्लास - स्थिर

उदाहरण:

$foobar = new Foobar(); 
$foobar->init($qux, ...); 
// $foobar ready for usage 

उदाहरण के एक ही के लिए, मान का कहना है कि $qux वस्तु केवल निर्भरता कि Foobar की जरूरत है। क्या मैं करने के लिए प्राप्त करना चाहते हैं है:

$foobar = Foo_Factory('bar'); 

क्रम पूरी प्रणाली भर में $qux वस्तु साथ भेज देते हैं और यह एक और पैरामीटर के रूप में कारखाने वर्ग के लिए पारित करने के लिए की जरूरत से बचने के लिए, मैं प्रदर्शन करने के लिए करना चाहते हैं कारखाने कक्षा में सीधे Foobar का प्रारंभ:

class Foo_Factory { 

    public static function getFoo($type) { 

     // some processing here 
     $foo_name = 'Foo' . $type; 
     $foo = new $foo_name(); 
     $foo->init($qux); 

     return $foo; 
    } 

} 

कुछ समाधान है कि दिमाग में आ रहे हैं, लेकिन उनमें से कोई आदर्श है:

  1. एक स्थिर सेटर मेथ जोड़े कारखाने वर्ग में $qux के लिए od, और इसे एक निजी स्थैतिक चर में $qux का संदर्भ संग्रहीत करने दें। सिस्टम शुरुआत में $qux सेट कर सकता है, और फैक्ट्री क्लास भविष्य में हुए बदलावों (सुरक्षा कारणों से) को रोक सकती है।
    हालांकि यह दृष्टिकोण काम करता है, $qux के संदर्भ में एक स्थिर पैरामीटर का उपयोग करके यूनिट परीक्षण के दौरान समस्याग्रस्त है (उदाहरण के लिए यह अपने स्थिर राज्य के कारण व्यक्तिगत परीक्षणों के बीच खुशी से रहता है)।
  2. सिंगलटन पैटर्न का उपयोग करके एक नया संदर्भ वर्ग बनाएं और कारखाने वर्ग को $qux का संदर्भ प्राप्त करने के लिए इसका उपयोग करें। विकल्प # 1 से ऐसा करने के लिए यह थोड़ा क्लीनर तरीका हो सकता है (हालांकि हम कारखाने वर्ग से संदर्भ वर्ग में स्थिर समस्या को स्थानांतरित करते हैं)।
  3. निर्भरता इंजेक्शन का उपयोग सभी तरह से करें, यानी $qux किसी भी ऑब्जेक्ट को फैक्ट्री क्लास का उपयोग करने के लिए पास करें, और उस ऑब्जेक्ट को फ़ैक्टरी क्लास के साथ अन्य पैरामीटर के रूप में पास करने दें: Foo_Factory::getFoo($type, $qux);
  4. उपर्युक्त (# 3) के समान, लेकिन सिस्टम के साथ $qux पास करने के बजाय, कारखाने वर्ग के उदाहरण को पास करें (यानी इस मामले में यह स्थैतिक नहीं होगा, लेकिन तत्काल)।

आप क्या सलाह देंगे? ऊपर वर्णित चार विकल्पों में से कोई भी, या कृपया ऐसा करने का एक बेहतर तरीका है?

नोट: मैं यहां सबसे अच्छे समाधान के साथ आने की कोशिश कर रहा हूं, यहां static is evil ज्वालामुखी में प्रवेश नहीं करना चाहता हूं।

उत्तर

5

मैं निर्भरता इंजेक्शन के साथ सभी तरह से जाऊंगा। लेकिन, हर जगह $ qux गुजरने के बजाय, बस इसे निर्भरता इंजेक्टर कंटेनर में पंजीकृत करें और कंटेनर को इसे सॉर्ट करने दें। Symfony Component बात में:

// Create DI container 
$container = new sfServiceContainerBuilder(); 

// Register Qux 
$container->setService('qux', $qux); 
// Or, to have the DI instanciate it 
// $container->register('qux', 'QuxClass'); 

// Register Foobar 
$container->register('foobar', 'Foobar') 
      ->addArgument(new sfServiceReference('qux')); 

// Alternative method, using the current init($qux) method 
// Look! No factory required! 
$container->register('altFoobar', 'Foobar') 
      ->addMethodCall('init', array(new sfServiceReference('qux'))); 
+0

आह, कि वास्तव में बहुत अच्छा है - मुझे लगता है कि मैं और अधिक विस्तार (व्यावहारिक रूप से) जब मैं एक मौका मिलता है में सिम्फनी पर गौर करना होगा। मैंने एक साधारण कंटेनर समाधान बनाया है, और जब भी मैं आंतरिक रूप से कारखानों का उपयोग कर रहा हूं, यह एक आकर्षण की तरह काम करता है :-) प्रतिक्रिया और उदाहरण के लिए धन्यवाद! – MicE

4

मैं सिर्फ फैक्टरी तरीकों गैर स्थिर बनाने के लिए और यह हर वस्तु है कि कि कारखाने की जरूरत को दे देते हैं।

कारखाने को स्थापित करने के लिए आपको इसे अपने $qux पैरामीटर के साथ निर्माता को खिलाना होगा।

class Foo_Factory { 

    public function __construct($qux) { 
     $this->qux = $qux; 
    } 

    public function getFoo($type) { 
     // some processing here 
     $foo_name = 'Foo' . $type; 
     $foo = new $foo_name(); 
     $foo->init($this->qux); 

     return $foo; 
    } 
} 
कि दृष्टिकोण आप वर्गों जहाँ आप एक सेवा कंटेनर या एक रजिस्ट्री के आसपास पारित "मुसीबत" बिना कारखाने के साथ काम करने की जरूरत में उपयोग की आसान मिलना चाहिए के साथ

इस उदाहरण के लिए मैं केवल उन वस्तुओं के आस-पास गुजरने के प्रत्यक्ष दृष्टिकोण का उपयोग करता हूं जो वास्तव में आपकी आवश्यकता है और सार तत्वों में नहीं हैं।

निर्णय है कि क्या एक डीआईसी या एक रजिस्ट्री या सादे पुराने डि उपयोग करने के लिए कुछ है कि, मुझे लगता है, अपने पूरे परियोजना के लिए किया जाना चाहिए है। मैं दृढ़ता से एक रजिस्ट्री पर एक डीआईसी पसंद करता हूं लेकिन सामान्य डी की तरह भी बेहतर। दिए गए संदर्भ के लिए किसी निश्चित दृष्टिकोण के लिए या उसके खिलाफ बहस करना मुश्किल है।

मेरी बात संक्षेप में: स्थिर कारखाने समस्या है, तो बस इसे गैर स्थिर हैं।

आशा है कि मैं अपनी पोस्ट सही समझा;)

+0

धन्यवाद एडोरियन। अंत में मैंने एक डीआईसी का उपयोग किया (क्योंकि वास्तव में मेरे पास '$ qux' से अधिक निर्भरता है), और इसे पूरे सिस्टम में लागू किया गया। इसने इसे स्वयं द्वारा महत्वपूर्ण रूप से साफ किया, यूनिट-टेस्टेबिलिटी में सुधारों का जिक्र नहीं किया :-) – MicE

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