2011-04-14 16 views
5

मैं PHP में फैक्ट्री पैटर्न को लागू करने के दो अलग-अलग तरीकों में से एक पर विचार कर रहा हूं। मुझे नहीं पता कि इन प्रकारों के उचित नाम हैं इसलिए अब मैं उन्हें आंतरिक कारखाना और बाहरी कारखाना कहूंगा।आंतरिक बनाम बाहरी कारखाना

आंतरिक कारखाना: कारखाने विधि एक स्थिर सार्वजनिक विधि के रूप में वर्ग अपने आप में कार्यान्वित किया जाता है

<?php 
class Foo 
{ 
    protected 
     $loadedProps = false; 

    public static factory ($id) 
    { 
     $class = get_called_class(); 
     $item = new $class ($id); 
     if ($item -> loadedProps()) 
     { 
      return ($item); 
     } 
    } 

    public function loadedProps() 
    { 
     return ($this -> loadedProps); 
    } 

    protected function loadPropsFromDB ($id) 
    { 
     // Some SQL logic goes here 
    } 

    protected function __construct ($id) 
    { 
     $this -> loadedProps = $this -> loadPropsFromDB ($id); 
    } 
} 
?> 

बाहरी कारखाना: कारखाने और आइटम यह initializes अलग संस्थाओं के रूप में लागू किया जाता है

<?php 

class Foo 
{ 
    protected 
     $loadedProps = false; 

    public function loadedProps() 
    { 
     return ($this -> loadedProps); 
    } 

    protected function loadPropsFromDB ($id) 
    { 
     // Some SQL logic goes here 
    } 

    public function __construct ($id) 
    { 
     $this -> loadedProps = $this -> loadPropsFromDB ($id); 
    } 
} 

abstract class FooFactory 
{ 
    public static factory ($id) 
    { 
     $item = new Foo ($id); 
     if ($item -> loadedProps()) 
     { 
      return ($item); 
     } 
    } 
} 
?> 

अब मुझे लगता है कि प्रत्येक के पास इसकी योग्यता है।

पूर्व आपको बाहरी दुनिया से निर्माता को छिपाने की अनुमति देता है। इसका मतलब है कि आप फू ऑब्जेक्ट बनाने का एकमात्र तरीका फैक्ट्री के माध्यम से कर सकते हैं। यदि आइटम की स्थिति डीबी से लोड नहीं की जा सकती है तो फैक्ट्री न्यूल लौटाएगी जिसे आप आसानी से कोड में देख सकते हैं।

if ($item = Foo::factory ($id)) 
{ 
    // ... 
} 
else 
{ 
    // The item failed to load. Handle error here 
} 

कारखाना किसी भी संशोधन के बिना फू के किसी भी उप-वर्ग की वस्तुएं भी बना सकता है।

हालांकि, ऐसा लगता है कि इसमें कुछ कमीएं हैं। सबसे पहले कक्षा को फैक्ट्री को लागू करना होता है, जो कक्षा में जिम्मेदारियां डाल सकता है जो वास्तव में कहीं और संबंधित है। आंतरिक फैक्ट्री संस्करण निश्चित रूप से बाहरी फैक्टरी संस्करण की तुलना में एक बड़ी कक्षा में परिणाम देता है।

बाहरी कारखाने के लिए, अच्छी तरह से यह साफ है क्योंकि फैक्ट्री कक्षा में नहीं है और मुझे किसी वर्ग के बारे में चिंता करने की आवश्यकता नहीं है जितनी चाहिए। बाह्य कारखाना निर्भरता इंजेक्शन के लिए बेहतर अनुकूल भी हो सकता है।

हालांकि, इसका अपना खुद का दोष है। सबसे पहले और सबसे महत्वपूर्ण, कारखाने में बनाए जाने वाले आइटम का निर्माता सार्वजनिक होना चाहिए क्योंकि PHP में पैकेज की अवधारणा नहीं है और वर्ग के सदस्यों के लिए 'पैकेज' सुरक्षा स्तर नहीं है। इसका मतलब है कि केवल नए फू() और फैक्ट्री को छोड़कर कोडर को रोकना कुछ नहीं है (हालांकि यह इकाई परीक्षण को आसान बना सकता है)।

दूसरी समस्या यह है कि FooFactory केवल फू ऑब्जेक्ट्स बना सकता है, न कि इसके किसी भी उप-वर्ग। यह कक्षा नाम निर्दिष्ट करने के लिए FooFactory में एक और पैरामीटर जोड़कर मिल सकता है, लेकिन फिर फैक्ट्री को आंतरिक जांच करना होगा कि निर्दिष्ट ऑब्जेक्ट क्लास वास्तव में फू के वंशज है।

तो मूल रूप से, दोनों दृष्टिकोणों की सापेक्ष योग्यता क्या है, और आप किसकी सिफारिश करेंगे?

इसके अलावा, अगर उनके पास आंतरिक या बाहरी कारखाने की तुलना में अधिक उचित नाम हैं, तो मैं उन्हें जानना चाहता हूं।

उत्तर

7

वास्तव में, कारखानों स्थापित कर रहे हैं क्रिएशनल डिजाइन पैटर्न है, तो आप में GOF बुक अपने उद्देश्य के बारे में या Sourcemaking:

  • सार फैक्टरी पर पढ़ सकते हैं - वर्गों के कई परिवारों का एक उदाहरण बनाता
  • बिल्डर - ऑब्जेक्ट निर्माण को इसके प्रतिनिधित्व से अलग करता है
  • फैक्टरी विधि - कई व्युत्पन्न कक्षाओं का एक उदाहरण बनाता है
  • वस्तु पूल - महंगा अधिग्रहण और संसाधनों की रिहाई वस्तुओं जो अब उपयोग में हैं रीसाइक्लिंग द्वारा बचें
  • प्रोटोटाइप - एक पूरी तरह से आरंभ उदाहरण नकल या क्लोन किए जाने की

वहाँ कुछ ओवरलैप है इन पैटर्नों में, विशेष रूप से फैक्टरी विधि, सार फैक्ट्री और बिल्डर के बीच और भेद तब भी अधिक धुंधला होता है जब आप वस्तुओं के परिवार नहीं बनाते हैं, बल्कि केवल एक प्रकार का ऑब्जेक्ट बनाते हैं। तो हाँ, सादगी के लिए, आइए मान लें कि आंतरिक और बाहरी कारखाने सही शब्द हैं।

व्यक्तिगत रूप से, मैं हमेशा से पहले दिए गए कारण के कारण एक आंतरिक फैक्ट्री पर एक बाहरी फैक्ट्री का पक्ष लेता हूं: मैं Dependency Injection का उपयोग कर सकता हूं और separate the responsibilities कर सकता हूं। चूंकि static methods are death to testability और considered harmful हो सकता है, जो उनके द्वारा पेश किए गए युग्मन के कारण हो सकता है, मैं फैक्ट्री को वास्तविक वस्तु बना दूंगा और इसके बजाय गैर स्थैतिक तरीकों का उपयोग करूंगा।

आपके द्वारा उल्लिखित दो दोष वास्तव में कम नहीं हैं।

मैं किसी कारण से नहीं सोच सकता कि मैं prevent a developer को फैक्ट्री बनाने वाली वस्तुओं को तत्काल करने से क्यों चाहता हूं। वास्तव में, जब Unit-Testing मैं उस वस्तु को अपने आप बनाना चाहता हूं और Mocks and Stubs के साथ किसी भी निर्भरता को प्रतिस्थापित करना चाहता हूं। I also dont believe that developers should be babysitted too much। PHP की स्क्रिप्ट प्रकृति को देखते हुए, सीटीओ को निजी से सार्वजनिक में बदलना किसी भी तरह से प्रभावी ढंग से रोका जा सकता है।

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

फैक्ट्रियों के अन्य व्यवहार्य विकल्प Dependency Injection Container का उपयोग करना होगा, जैसे Symfony Components DIC और अधिकतर कंटेनर के माध्यम से अपनी ऑब्जेक्ट्स का प्रबंधन करें।

+0

'ऑफ-विषय: 'एक यादृच्छिक नोट पर मुझे यह विनोदी लगता है कि आप दोनों एक ही चीज़ के बारे में बात कर रहे हैं जब आपके पास एक ही उपयोगकर्ता नाम है। एक सेकंड के लिए मैंने सोचा कि आप खुद से बात कर रहे थे। – Tek

+0

@ टेक हाँ, गॉर्डन ने गॉर्डन का जवाब दिया। लेकिन मैं गॉर्डन ™ हूँ :) – Gordon

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