2012-04-20 7 views
6

मैं this article में प्रस्तावित पूरी तरह से मॉड्यूलर बनाने के लिए कुछ सॉफ्टवेयर सिस्टम के विभाजन भागों के लिए केक पैटर्न का उपयोग करना चाहता हूं। सबसे सरल मामले में, मुझे कुछ मॉक करने योग्य घटक चाहिए, चलिए लॉगिंग, कॉन्फ़िगर, डेटाबेस, स्क्रिप्ट आदि कहें जो संभावित रूप से एक दूसरे का उपयोग कर सकते हैं। कोडस्कैला केक पैटर्न: बड़े घटकों को अलग-अलग फाइलों में विभाजित करना

trait AbstractConfig { 
    def config: AbstractConfigInterface 
    trait AbstractConfigInterface { 
    def test: Unit 
    } 
} 

trait SomeConfig extends AbstractConfig { 
    this: Core => 
    def config = SomeConfigImplementation 
    object SomeConfigImplementation extends AbstractConfigInterface { 
    def test = println("conf.test method called") 
    } 
} 

trait AbstractDatabase { 
    def database: AbstractDatabaseInterface 
    trait AbstractDatabaseInterface { 
    def connect: Unit 
    } 
} 

trait SomeDatabase extends AbstractDatabase { 
    this: Core => 
    def database = SomeDatabaseImplementation 
    object SomeDatabaseImplementation extends AbstractDatabaseInterface { 
    def connect = { 
     println("connect method called") 
     core.conf.test 
    } 
    } 
} 

trait Core { 
    this: AbstractDatabase with AbstractConfig => 
    def core = CoreInterface 
    object CoreInterface { 
    def db = database 
    def conf = config 
    } 
} 

object app extends Core with SomeDatabase with SomeConfig 

object Run { 
    def main(args: Array[String]) = { 
    app.core.db.connect 
    } 
} 

यहाँ डेटाबेस और config घटकों (SomeConfig और SomeDatabase लक्षण) कैसा लग सकता है प्लगेबल कर रहे हैं और अगर कभी जरूरत कुछ अन्य कार्यान्वयन के लिए बदला जा सकता है। उनके कार्यान्वयन के पास core ऑब्जेक्ट तक पहुंच है जो डेटाबेस और कॉन्फ़िगरेशन दोनों रखती है, इसलिए यदि आवश्यक हो तो डेटाबेस कॉन्फ़िगरेशन तक पहुंच सकता है और इसके विपरीत।

तो सवाल यह है कि: यदि कभी SomeDatabase जैसी कुछ विशेषता बड़ी हो जाती है और core ऑब्जेक्ट तक पहुंच को बनाए रखने के लिए अलग-अलग वर्गों में विभाजित करने के लिए एक फ़ाइल में फिट नहीं होती है? अधिक विशिष्ट होना करने के लिए, मान लीजिए कि मैं एक और फाइल करने के लिए SomeDatabase में कनेक्ट विधि से बाहर कुछ कोड बढ़ने की जरूरत है:

// SomeDatabase.scala 
trait SomeDatabase extends AbstractDatabase { 
    this: Core => 
    def database = SomeDatabaseImplementation 
    object SomeDatabaseImplementation extends AbstractDatabaseInterface { 
    def connect = { 
     val obj = new SomeClass() 
    } 
    } 
} 

// SomeClass.scala in the same package 
class SomeClass { 
    core.conf.test // Does not compile - how to make it work?? 
} 

SomeClass कैसे SomeDatabase कार्यों के कार्यान्वयन विवरण है, इसलिए मैं स्पष्ट रूप से यह एक बनाने के लिए नहीं करना चाहते हैं विशेषता है और इसे आवेदन में मिलाएं। SomeClass के लिए core ऑब्जेक्ट तक पहुंच प्रदान करने का कोई तरीका है?


कुछ संबंधित लिंक:

  1. Dependency Injection vs Cake Pattern by Jan Machacek
  2. Real World Scala: Dependency Injection by Jonas Boner
  3. Dependency Injection in Scala: Extending the Cake Pattern by Adam Warsky
  4. Scalable Component Abstractions by Martin Odersky & Matthias Zenger

उत्तर

2

होगा करने का सबसे आसान बात SomeClass पर एक निर्माता पैरामीटर के रूप में Core पास करने के लिए।

// SomeDatabase.scala 
trait SomeDatabase extends AbstractDatabase { 
    this: Core => 
    def database = SomeDatabaseImplementation 
    object SomeDatabaseImplementation extends AbstractDatabaseInterface { 
    def connect = { 
     val obj = new SomeClass(SomeDatabase.this) // pass it here 
    } 
    } 
} 

// SomeClass.scala in the same package 
class SomeClass(coreComp: Core) { // use it here 
    coreComp.core.conf.test 
} 

दिलचस्प है, मैं वास्तव में सिर्फ CoreInterface या AbstractConfigInterface पारित करने के लिए चाहता था, लेकिन तथ्य यह है कि वे आंतरिक प्रकार के होते हैं वास्तव में है कि मुश्किल बना दिया।

+0

डेव, उत्तर के लिए धन्यवाद। अब तक यह एकमात्र उचित तरीका प्रतीत होता है। एकमात्र चीज जिसे मैं इसके बारे में नहीं खोता हूं, किसी भी कोर विधि के प्रत्येक आमंत्रण में 'coreComp.' टाइप करने की आवश्यकता है। दुर्भाग्य से 'CoreInterface' के साथ काम करने का विकल्प प्रतीत नहीं होता है, है ना? – nab

+1

टाइपिंग को कम करने के लिए आप 'CoreComp._' आयात कर सकते हैं। – leedm777

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