2016-05-17 6 views
21

मैं Play! Framework का उपयोग Scala के लिए लगभग एक साल से कर रहा हूं। मैं वर्तमान में संस्करण 2.5.x का उपयोग कर रहा हूं।प्ले फ्रेमवर्क में स्कैला के ऑब्जेक्ट पर @ सिंगलेटन का उपयोग क्यों करें?

मुझे प्ले में नियंत्रकों के विकास और कैसे डेवलपर्स को स्थिर object मार्गों से दूर मजबूर किया गया है।

मुझे खेल में Guice उपयोग के बारे में भी पता है।

आप activator डाउनलोड करने और चलाते हैं:

activator new my-test-app play-scala 

उत्प्रेरक आप के लिए एक टेम्पलेट परियोजना का उत्पादन करेगा। मेरा प्रश्न विशेष रूप से उस टेम्पलेट की this फ़ाइल के आसपास है।

मेरी परीक्षण एप्लिकेशन के अंतर्गत/ऐप्स/सेवाओं/Counter.scala

package services 

import java.util.concurrent.atomic.AtomicInteger 
import javax.inject._ 

/** 
* This trait demonstrates how to create a component that is injected 
* into a controller. The trait represents a counter that returns a 
* incremented number each time it is called. 
*/ 
trait Counter { 
    def nextCount(): Int 
} 

/** 
* This class is a concrete implementation of the [[Counter]] trait. 
* It is configured for Guice dependency injection in the [[Module]] 
* class. 
* 
* This class has a `Singleton` annotation because we need to make 
* sure we only use one counter per application. Without this 
* annotation we would get a new instance every time a [[Counter]] is 
* injected. 
*/ 
@Singleton 
class AtomicCounter extends Counter { 
    private val atomicCounter = new AtomicInteger() 
    override def nextCount(): Int = atomicCounter.getAndIncrement() 
} 

तुम भी this फ़ाइल में इसके उपयोग देख सकते हैं:

मेरी परीक्षण एप्लिकेशन के अंतर्गत/ऐप्स/नियंत्रकों /CountController.scala

package controllers 

import javax.inject._ 
import play.api._ 
import play.api.mvc._ 
import services.Counter 

/** 
* This controller demonstrates how to use dependency injection to 
* bind a component into a controller class. The class creates an 
* `Action` that shows an incrementing count to users. The [[Counter]] 
* object is injected by the Guice dependency injection system. 
*/ 
@Singleton 
class CountController @Inject() (counter: Counter) extends Controller { 

    /** 
    * Create an action that responds with the [[Counter]]'s current 
    * count. The result is plain text. This `Action` is mapped to 
    * `GET /count` requests by an entry in the `routes` config file. 
    */ 
    def count = Action { Ok(counter.nextCount().toString) } 

} 

यह हर नियंत्रक जो निर्माण किया है इसका मतलब है या @Inject() (counter: Counter) का Counter का एक ही उदाहरण प्राप्त होगा।

तो मेरे सवाल है:

क्यों @Singleton का उपयोग करें और फिर इसे @Inject एक नियंत्रक में, जब इस उदाहरण के लिए आप सिर्फ एक स्काला वस्तु इस्तेमाल कर सकते हैं?
इसका बहुत कम कोड है।

उदाहरण:

मेरी परीक्षण एप्लिकेशन के अंतर्गत/ऐप्स/सेवाओं/Counter.scala

package services 

trait ACounter { 
    def nextCount: Int 
} 

object Counter with ACounter { 
    private val atomicCounter = new AtomicInteger() 
    def nextCount(): Int = atomicCounter.getAndIncrement() 
} 

यह इतना की तरह उपयोग करें:

मेरी परीक्षण एप्लिकेशन के अंतर्गत/ऐप्स/नियंत्रक/countController.scala

package controllers 

import javax.inject._ 
import play.api._ 
import play.api.mvc._ 

import services.{Counter, ACounter} 

/** 
* This controller demonstrates how to use dependency injection to 
* bind a component into a controller class. The class creates an 
* `Action` that shows an incrementing count to users. The [[Counter]] 
* object is injected by the Guice dependency injection system. 
*/ 
@Singleton 
class CountController extends Controller { 
    //depend on abstractions 
    val counter: ACounter = Counter 

    def count = Action { Ok(counter.nextCount().toString) } 

} 

क्या अंतर है? इंजेक्शन पसंदीदा है, और क्यों?

+2

इससे कोई फर्क नहीं पड़ता कि आपको पैरामीटर पास करने की आवश्यकता नहीं है आपके नियंत्रक के लिए। लेकिन यदि आप करते हैं, तो इसे निर्भरता को इंजेक्ट करने और इंजेक्ट करने के लिए गुइस के लिए एक वर्ग होना आवश्यक है। –

उत्तर

13

इंजेक्शन पसंदीदा तरीका है? आम तौर पर हाँ

निर्भरता इंजेक्शन का उपयोग कर के एक जोड़े को फायदे: Counter के ठोस कार्यान्वयन से

  1. दसगुणा नियंत्रक।
    • यदि आप object का उपयोग करना चाहते थे, तो आपको विभिन्न कार्यान्वयन को इंगित करने के लिए अपने नियंत्रक को बदलना होगा।ईजी Counter2.nextCount().toString
  2. आप Guice कस्टम बाइंडिंग का उपयोग कर
    • चलें कहना Counter की है कि अंदर आप एक WS कॉल कर रहे हैं परीक्षण के दौरान कार्यान्वयन भिन्न हो सकते हैं। इससे कुछ कठिनाई इकाई परीक्षण हो सकता है। यदि आप गुइस के साथ निर्भरता इंजेक्शन का उपयोग कर रहे हैं, तो आप Counter और AtomicCounter के बीच बाध्यकारी को Counter के ऑफ़लाइन संस्करण को इंगित करने के लिए ओवरराइड कर सकते हैं जिसे आपने विशेष रूप से अपने परीक्षणों के लिए लिखा है। Guice for Play परीक्षणों का उपयोग करने के बारे में अधिक जानकारी के लिए here देखें।

इसके अलावा motivations कि प्ले डि ओर पलायन के लिए था देखते हैं।

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

3

मुझे यकीन नहीं कर रहा हूँ अगर मैं अपने प्रश्न को समझने, लेकिन क्योंकि इंजेक्शन पसंद किया जाता है:

  • आपके आवेदन के विभिन्न भागों कम युग्मित
  • यह अलग वर्ग प्रदान करने के साथ अपनी निर्भरता को बदलने के लिए आसान है एक ही कार्यक्षमता (यदि आपको भविष्य में ऐसा करने की आवश्यकता होगी) - आपको कोड की कुछ पंक्तियों को बदलने की आवश्यकता होगी और आपकी ऑब्जेक्ट की सभी घटनाओं को देखने की आवश्यकता नहीं है
  • परीक्षण करना आसान है (विशेष रूप से जब आपको कुछ नकल करने की आवश्यकता होती है)

संक्षेप में बोलते हुए: सोलिड सिद्धांतों से डी: "एब्स्ट्रैक्शन पर निर्भर करता है। विवेक पर निर्भर न करें "

4

शायद क्योंकि स्कैला के सिंगलटन ऑब्जेक्ट में पैरामीटर नहीं हो सकते हैं? उदाहरण के लिए, यदि आपके पास एक सेवा कक्षा है जिसमें डीएओ इंजेक्शन है, और आप नियंत्रक में सेवा का उपयोग करना चाहते हैं, तो आपको इंजेक्ट करना होगा यह सबसे आसान तरीका (आईएमओ) गुइस के साथ DI है ... इसके अलावा, आप अपनी निर्भरताओं को एक स्थान (मॉड्यूल) आदि में प्राप्त कर सकते हैं ...

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