2009-07-04 12 views
6

रूबी में निर्भरता इंजेक्शन ढांचे को बहुत अधिक अनावश्यक घोषित किया गया है। जामिस बक ने पिछले साल अपने LEGOs, Play-Doh, and Programming ब्लॉग पोस्ट में लिखा था।रुबी

सामान्य स्वीकृत विकल्प कुछ डिग्री कन्स्ट्रक्टर इंजेक्शन का उपयोग कर रहा है, लेकिन केवल डिफ़ॉल्ट की आपूर्ति करता है।

class A 
end 

class B 
    def initialize(options={}) 
    @client_impl = options[:client] || A 
    end 

    def new_client 
    @client_impl.new 
    end 
end 

यह दृष्टिकोण मेरे द्वारा ठीक है, लेकिन यह अधिक परंपरागत व्यवस्था से एक बात की कमी है लगता है: कुछ बाहरी स्विच के आधार पर रनटाइम पर कार्यान्वयन प्रतिस्थापन का एक तरीका।

एक निर्भरता इंजेक्शन ढांचे मैं इस तरह (pesudo-सी #) कुछ कर सकते हैं के साथ उदाहरण के लिए:

if (IsServerAvailable) 
    container.Register<IChatServer>(new CenteralizedChatServer()); 
else 
    container.Register<IChatServer>(new DistributedChatServer()); 

यह उदाहरण सिर्फ है कि क्या हमारे centeralized सर्वर उपलब्धता के आधार पर एक अलग IChatServer कार्यान्वयन पंजीकृत करता है।

चूंकि हम अभी भी रूबी में कन्स्ट्रक्टर का उपयोग कर रहे हैं, हमारे पास उपयोग की जाने वाली निर्भरताओं पर प्रोग्रामिक नियंत्रण नहीं है (जब तक हम प्रत्येक को स्वयं निर्दिष्ट नहीं करते)। उदाहरण जेमिस कक्षाओं को और अधिक टेस्ट करने योग्य बनाने के लिए उपयुक्त लगता है, लेकिन प्रतिस्थापन के लिए सुविधाओं की कमी लगती है।

मेरा प्रश्न क्या है, आप रूबी में इस स्थिति को कैसे हल करते हैं? मैं किसी भी उत्तर के लिए खुला हूं, जिसमें "आपको बस ऐसा करने की आवश्यकता नहीं है"। मैं सिर्फ इन मामलों पर रूबी परिप्रेक्ष्य को जानना चाहता हूं।

उत्तर

8

कन्स्ट्रक्टर प्रतिस्थापन के अतिरिक्त, आप जानकारी को आवृत्ति चर ("विशेषता") में संग्रहीत कर सकते हैं। अपने उदाहरण से:

class A 
end 

class B 
    def connect(impl = nil) 
    impl ||= Twitterbot 
    @connection = impl.new.connect 
    end 
end 

b = B.new 
b.connect 

b = B.new 
b.connect(Facebookbot) 

तुम भी सकता है मिश्रण-एवं-मिलान तकनीक:

class A 
end 

class B 
    attr_accessor :impl 

    def initialize(impl = nil) 
    @impl = impl || Twitterbot 
    end 

    def connect(impl = @impl) 
    @connection = impl.new.connect 
    end 
end 

b = B.new 
b.connect # Will use Twitterbot 

b = B.new(Facebookbot) 
b.connect # Will use Facebookbot 

b = B.new 
b.impl = Facebookbot 
b.connect # Will use Facebookbot 

b = B.new 
b.connect(Facebookbot) # Will use Facebookbot 

class A 
end 

class B 
    attr_accessor :client_impl 

    def connect 
    @connection = @client_impl.new.connect 
    end 
end 

b = B.new 
b.client_impl = Twitterbot 
b.connect 

तुम भी निर्भरता को विधि के लिए एक विकल्प के रूप में उपलब्ध कराया जा अनुमति दे सकता है

असल में, जब लोग रूबी और डीआई के बारे में बात करते हैं, तो उनका क्या मतलब है कि भाषा स्वयं एक विशेष रूपरेखा की आवश्यकता के बिना DI की शैलियों को लागू करने के लिए पर्याप्त लचीला है।