2010-11-16 7 views
26

वर्तमान में जब मुझे विभिन्न नियंत्रकों के बीच processParams(params) जैसी विधि साझा करने की आवश्यकता है, तो मैं या तो विरासत या सेवाओं का उपयोग करता हूं। ,आप अलग-अलग grails नियंत्रकों में सामान्य तरीकों को कैसे साझा करते हैं?

    विरासत के साथ
  • आप एकाधिक वंशानुक्रम जिसका अर्थ है कि आप एक ही स्थान पर अपने नियंत्रक उपयोगिता पद्धतियों का अनुपालन करने की आवश्यकता का उपयोग नहीं कर सकते हैं: दोनों समाधान कुछ inconvenients है। और साथ ही, Grails में एक बग है जो विकास मोड में बेस कंट्रोलर कक्षाओं में किसी भी कोड परिवर्तन का पता नहीं लगाता है (आपको ऐप को पुनरारंभ करने की आवश्यकता है)
  • सेवाओं के साथ, आपके पास पैराम जैसे सभी इंजेक्शन गुणों तक पहुंच नहीं है, सत्र, फ्लश ...

तो मेरा सवाल है: क्या एकाधिक नियंत्रकों के लिए सुलभ कुछ सामान्य तरीकों का उपयोग करने का कोई अन्य तरीका है?

उत्तर

3

यह आपके पास विकास मोड समस्या में पुनरारंभ करने में मदद नहीं करता है, लेकिन इस तरह मैंने इस समस्या को हल किया है। यह बदसूरत और शायद अच्छा अभ्यास नहीं है, लेकिन मैं कक्षाओं में सामान्य कोड को बंद करने के रूप में कारक करता हूं। तब मैं कुछ ऐसा कर सकते हैं: controllerClosures कक्षा में साथ

new ControllerClosures().action(this) 

और से

def action={ 
    it.response.something 
    return [allYourData] 
} 
2

आप उपयोग कर सकते हैं Delegation design pattern:

class Swimmer { 
    def swim() { "swimming" } 
} 

class Runner { 
    def run() { "running" } 
} 

class Biker { 
    def bike() { "biking" } 
} 

class Triathlete { 
    @Delegate Swimmer swimmer 
    @Delegate Runner runner 
    @Delegate Biker biker 
} 

def triathlete = new Triathlete(
    swimmer: new Swimmer(), 
    runner: new Runner(), 
    biker: new Biker() 
) 

triathlete.swim() 
triathlete.run() 
triathlete.bike() 

एक नियंत्रक के मामले में, सहायक आवंटित उदाहरण क्षेत्र में सीधे कक्षा (या नलिका कन्स्ट्रक्टर में):

class HelperClass { 
    def renderFoo() { render 'foo' } 
} 

class FooController { 
    private @Delegate HelperClass helperClass = new HelperClass() 

    def index = { this.renderFoo() } 
} 

delegate की प्रकार की जानकारी युक्त कक्षा में संकलित हो जाती है।

+6

प्रतिनिधि वर्ग इस तरह के विधि या पैरामीटर प्रस्तुत करना के रूप में मालिक वर्ग के आंतरिक भागों, के लिए पहुँच नहीं है सकते हैं । – ataylor

+2

दुर्भाग्य से यह सच है, और इस प्रकार '@ प्रतिनिधि' इस मामले में पसंद की पद्धति नहीं होगी। – robbbert

22

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

यहाँ एक छोटे से उदाहरण है:

@Category(Object) 
class MyControllerCategory { 
    def printParams() { 
     println params 
    } 
} 

@Mixin(MyControllerCategory) 
class SomethingController { 

    def create = { 
     printParams() 
     ... 
    } 

    def save = { 
     printParams() 
    } 
} 
+7

दरअसल, आपको '@ मिक्सिन एनोटेशन का उपयोग करने के लिए' @ श्रेणी' एनोटेशन की आवश्यकता नहीं है। - आपको वैकल्पिक विधि 'SomethingController.mixin ([MyControllerCategory])' का उपयोग करते समय केवल इसकी आवश्यकता होगी (''static' method' printParams()' प्रदान करने के लिए 'MyControllerCategory' की आवश्यकता होती है)। ग्रोवी दस्तावेज़ आपके समान नमूने प्रदान करते हैं, लेकिन यह आवश्यक नहीं है। - यह गलतफहमी इस तथ्य के कारण हो सकती है कि * श्रेणियों * का उपयोग एक विकासवादी प्रक्रिया से गुज़र रहा है - एक बार सिंटैक्स द्वारा बेकार होने के कारण, और अब '@ मिक्सिन' एनोटेशन द्वारा अधिग्रहण किया जा रहा है। – robbbert

+2

अंत में, '@ मिक्सिन' और '@ प्रतिनिधि' के बीच प्रमुख अंतर यह है कि * प्रतिनिधि * विधियों को लक्ष्य वर्ग में स्थिर रूप से संकलित किया जाता है जबकि * मिक्सिन * विधियों को रनटाइम पर बुलाया जाता है। – robbbert

+0

क्या निर्भरता इंजेक्शन के अधीन 'MyControllerCategory' बनाने का कोई तरीका है? –

3

आम कार्यक्षमता एक नया वर्ग के लिए एक कॉल, जरूरी नहीं कि आम पूर्वज है। प्रश्न बनाने के लिए जिम्मेदारी बयान खो रहा है। कहने की जरूरत नहीं है, यह एक जिम्मेदारी है कि हम एक नई कक्षा बनाते हैं। मैं वर्ग जिम्मेदारी के आधार पर और निर्णय लेता हूं।

मैं robbbert की और जारेड के जवाब में से एक संकर पसंद करते हैं: मैं अतिरिक्त कक्षाओं का निर्माण, उन्हें पैरामीटर के रूप में आवश्यक नियंत्रक आंतरिक गुजर। कभी-कभी कक्षा method objects से विकसित होती है। तरह:

def action = { 
    def doer = SomeResponsibilityDoer(this.request, this.response) 
    render doer.action() 
} 

ऐसा नहीं है संक्षिप्त है, लेकिन आप परीक्षण के तहत कोड प्राप्त और युग्मन को कम रखने की सुविधा देता है।

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

यह भी SomeResponsibilityDoer देव में नियंत्रक परिवर्तन पर पुनः लोड नहीं होने एक बड़ी बात नहीं है, क्योंकि:

  1. प्रारंभ में, आप इसे नियंत्रक फ़ाइलों में से कुछ में घोषणा कर सकते हैं - यह पुनः लोड किया जाएगा। इसे पूरा करने के बाद, उम्मीद है कि यह अक्सर नहीं बदलेगा, इसलिए इसे src/groovy पर ले जाएं।
  2. और भी महत्वपूर्ण बात यह है कि एप्लिकेशन के चलते और कंटोलर को पुनः लोड करने के बजाय यूनिट परीक्षणों के तहत डिज़ाइन के विकास के लिए यह तेज़ और बेहतर है।
1

आप commonService में सभी आम तरीका लिख ​​सकते हैं और है कि सेवा का उपयोग commmon विधि envoke को

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