2017-01-07 6 views
5

मैं केक पैटर्न के बारे में जानने की कोशिश कर रहा हूं।केक पैटर्न - यह इतना जटिल क्यों है

मैं इसके बारे में this ब्लॉग पढ़ रहा हूं।

कि ब्लॉग से उदाहरण कोड है:

case class User (name:String,email:String,supervisorId:Int,firstName:String,lastName:String) 

trait UserRepository { 
    def get(id: Int): User 
    def find(username: String): User 
} 
trait UserRepositoryComponent { 

    def userRepository: UserRepository 

    trait UserRepository { 
    def get(id: Int): User 
    def find(username: String): User 
    } 
} 
trait Users { 
    this: UserRepositoryComponent => 

    def getUser(id: Int): User = { 
    userRepository.get(id) 
    } 

    def findUser(username: String): User = { 
    userRepository.find(username) 
    } 
} 
trait UserInfo extends Users { 
    this: UserRepositoryComponent => 

    def userEmail(id: Int): String = { 
    getUser(id).email 
    } 

    def userInfo(username: String): Map[String, String] = { 
    val user = findUser(username) 
    val boss = getUser(user.supervisorId) 
    Map(
     "fullName" -> s"${user.firstName} ${user.lastName}", 
     "email" -> s"${user.email}", 
     "boss" -> s"${boss.firstName} ${boss.lastName}" 
    ) 
    } 
} 
trait UserRepositoryComponentImpl extends UserRepositoryComponent { 

    def userRepository = new UserRepositoryImpl 

    class UserRepositoryImpl extends UserRepository { 

    def get(id: Int) = { 
     ??? 
    } 

    def find(username: String) = { 
     ??? 
    } 
    } 
} 

object UserInfoImpl extends 
    UserInfo with 
    UserRepositoryComponentImpl 

मैं Users निकाल कर उस कोड को आसान बनाने में कर सकते हैं:

package simple { 

    case class User(name: String, email: String, supervisorId: Int, firstName: String, lastName: String) 

    trait UserRepository { 
    def get(id: Int): User 

    def find(username: String): User 
    } 

    trait UserRepositoryComponent { 

    def userRepository: UserRepository 

    trait UserRepository { 
     def get(id: Int): User 

     def find(username: String): User 
    } 

    } 

    trait UserInfo { 
    this: UserRepositoryComponent => 

    def userEmail(id: Int): String = { 
     userRepository.get(id).email 
    } 

    def userInfo(username: String): Map[String, String] = { 
     val user = userRepository.find(username) 
     val boss = userRepository.get(user.supervisorId) 
     Map(
     "fullName" -> s"${user.firstName} ${user.lastName}", 
     "email" -> s"${user.email}", 
     "boss" -> s"${boss.firstName} ${boss.lastName}" 
    ) 
    } 
    } 

    trait UserRepositoryComponentImpl extends UserRepositoryComponent { 

    def userRepository = new UserRepositoryImpl 

    class UserRepositoryImpl extends UserRepository { 

     def get(id: Int) = { 
     ??? 
     } 

     def find(username: String) = { 
     ??? 
     } 
    } 

    } 

    object UserInfoImpl extends 
    UserInfo with 
    UserRepositoryComponentImpl 

} 

और यह सिर्फ ठीक संकलित करता है।

1) ब्लॉग में कोड इतना जटिल क्यों है?

2) क्या यह केक पैटर्न का उपयोग करने का बेवकूफ तरीका है?

3) इस उदाहरण में Users कक्षा क्यों आवश्यक है?

4) कि जिस तरह से केक पैटर्न (की तरह लग रहे करने की अपेक्षा की है कि प्रतीत होता है अनावश्यक Users वर्ग के साथ है?

5) या सरलीकृत संस्करण ठीक है?

+1

ब्लॉग में एक टिप्पणी अनुभाग है। लेखक से पूछना शुरू क्यों नहीं करते? – pedrorijo91

+0

:) :) :) :) :) :) - आप मजाकिया हैं – jhegedus

+0

क्षमा करें, ध्यान नहीं दिया, सिर्फ 3 साल पहले टिप्पणी देखी .. ** मैंने कोड ** में बहुत कुछ खोला नहीं है, लेकिन मुझे लगता है कि यह सिर्फ एक और संकेत स्तर है।यदि आप उस व्यवहार को मॉक/स्टब करना चाहते हैं तो परीक्षण में मदद कर सकते हैं – pedrorijo91

उत्तर

8
  1. सबसे पहले यह जटिल हो सकता है, लेकिन एक बार जब आप उस पैटर्न से परिचित हो जाते हैं तो यह ... बॉयलरप्लाटी और बोझिल है। आपकी हर सेवा के लिए आपको एक साथ घटक बनाना होगा जो उस सेवा को लपेटेगा। तो प्रदान किए गए उदाहरण में आपके पास UserRepository है जो UserRepositoryComponent द्वारा लिपटा हुआ है। और यह केवल अमूर्त है, इसलिए आपको घटक और सेवा दोनों के लिए एक ठोस कार्यान्वयन की आवश्यकता है (यानी UserRepositoryComponentImpl रैपिंग UserRepositoryImpl)। और अब तक आपके पास केवल एक ही सेवा है जिसका उपयोग आपके मॉड्यूल में किया जा सकता है, दर्जनों सेवाओं को बनाने के प्रयास की कल्पना करें;)

  2. हां, यह उस पैटर्न का उपयोग करने का बेवकूफ तरीका है। हालांकि उस पैटर्न के अन्य रूप भी हैं, उदा। thin cake pattern या parfait (एक शब्द डिक दीवार द्वारा गढ़ा)

  3. आप User बारे में पूछ रहे हैं, फिर भी अपने कोड सरलीकरण Users दूर करने के लिए किया गया था, तो मैं उन दोनों का वर्णन करेंगे। User एक साधारण मामला वर्ग है, जो उस उदाहरण को समझने के लिए अधिक सुलभ/आसान बनाना चाहिए। Users हालांकि यहां जरूरी नहीं थे (यह केवल एक और मध्यवर्ती स्तर का अमूर्त स्तर है), और मेरी राय में वे उदाहरण के लिए कुछ अनावश्यक शोर लाते हैं।

  4. मैं कहूंगा कि आपका सरलीकृत संस्करण बिल्कुल दिखाता है कि केक पैटर्न कैसा दिखना चाहिए। आपके पास UserRepositoryComponent के अंदर लपेटा गया है, आपके पास उन दोनों गुणों का ठोस कार्यान्वयन है, और आपके पास कुछ सेवा (UserInfo) है जिसके लिए उपयोगकर्ताओं की भंडार की आवश्यकता होती है (जिसे स्वयं-प्रकार एनोटेशन का उपयोग करके "इंजेक्शन" दिया जाता है)।

  5. पहले ही उत्तर दिया गया है।

+0

विस्तृत स्पष्टीकरण के लिए धन्यवाद, मैंने प्रश्न 3 और 4 को सही किया, वास्तव में मेरा मतलब 'उपयोगकर्ता' था, इसलिए लेखन 'उपयोगकर्ता' एक टाइपो मैंने बनाया था। – jhegedus

+1

दुर्भाग्य से, मैं इस विस्तृत उत्तर के लिए केवल एक वोट दे सकता हूं। – ipoteka

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