उदाहरणों के साथ Kotlin में डिज़ाइन पैटर्न: उन्नत स्तर
प्रारंभिक स्तर पर, डेवलपर्स क्लासिक पैटर्न सीखते हैं: Singleton, Factory, Observer। हालाँकि, जटिल, स्केलेबल सिस्टम बनाते समय अधिक सूक्ष्म आर्किटेक्चरल ट्यूनिंग की आवश्यकता होती है। इस लेख में, हम Kotlin पर चार उन्नत डिज़ाइन पैटर्न का विश्लेषण करेंगे: कम्पोज़िट, विज़िटर, स्टेट और ब्रिज। प्रत्येक पैटर्न को एक व्यावहारिक कोड उदाहरण और यह बताकर चित्रित किया जाएगा कि इसे कब लागू किया जाना चाहिए।
1. कम्पोज़िट पैटर्न (Composite)
कम्पोज़िट पैटर्न क्लाइंट को अलग-अलग ऑब्जेक्ट और उनके समूहों के साथ एक समान रूप से काम करने की अनुमति देता है। यह पदानुक्रमित संरचनाएँ बनाने के लिए एक आदर्श समाधान है, जैसे फ़ाइल सिस्टम, इंटरफ़ेस मेनू या ग्राफ़िकल सीन।
Kotlin में, हम अक्सर ट्री नोड्स को प्रस्तुत करने के लिए sealed क्लास का उपयोग करते हैं। "फ़ाइलें और फ़ोल्डर" संरचना बनाने का एक उदाहरण देखें:
sealed class FileSystemNode(open val name: String) { data class File(override val name: String, val size: Long) : FileSystemNode(name) data class Directory( override val name: String, val children: MutableList<FileSystemNode> = mutableListOf() ) : FileSystemNode(name) { fun add(node: FileSystemNode) { children.add(node) } fun remove(node: FileSystemNode) { children.remove(node) } fun getTotalSize(): Long = children.sumOf { when (it) { is File -> it.size is Directory -> it.getTotalSize() } } }}
// उपयोगfun main() { val root = FileSystemNode.Directory("root") root.add(FileSystemNode.File("readme.txt", 1024)) val subDir = FileSystemNode.Directory("src") subDir.add(FileSystemNode.File("main.kt", 4096)) root.add(subDir) println("कुल आकार: ${root.getTotalSize()} बाइट") // 5120}लाभ: क्लाइंट कोड को सरल बनाता है, रिकर्सिव ऑपरेशन का समर्थन करता है। नुकसान: यदि ट्री बहुत गहरा है तो सिस्टम को जटिल बना सकता है।
2. विज़िटर पैटर्न (Visitor)
विज़िटर उनके वर्गों को बदले बिना ऑब्जेक्ट में नए ऑपरेशन जोड़ने की अनुमति देता है। यह विशेष रूप से तब उपयोगी होता है जब आपके पास एक स्थिर वर्ग पदानुक्रम होता है, लेकिन अक्सर बदलते प्रसंस्करण एल्गोरिदम होते हैं।
Kotlin में, यह sealed क्लास के साथ अच्छी तरह से काम करता है। आकृतियों के लिए क्षेत्रफल की गणना करने का एक उदाहरण लागू करें:
sealed class Shapeclass Circle(val radius: Double) : Shape()class Rectangle(val width: Double, val height: Double) : Shape()
interface ShapeVisitor<T> { fun visit(circle: Circle): T fun visit(rectangle: Rectangle): T}
class AreaCalculator : ShapeVisitor<Double> { override fun visit(circle: Circle) = Math.PI * circle.radius * circle.radius override fun visit(rectangle: Rectangle) = rectangle.width * rectangle.height}
// उपयोगfun <T> Shape.accept(visitor: ShapeVisitor<T>): T = when (this) { is Circle -> visitor.visit(this) is Rectangle -> visitor.visit(this)}
fun main() { val shapes = listOf(Circle(5.0), Rectangle(3.0, 4.0)) val calculator = AreaCalculator() shapes.forEach { println("क्षेत्रफल: ${it.accept(calculator)}") }}कब लागू करें: यदि ऑब्जेक्ट संरचना शायद ही कभी बदलती है, और उन पर ऑपरेशन अक्सर बदलते हैं। Kotlin में, सरल मामलों के लिए when का उपयोग किया जा सकता है, लेकिन कई प्रकारों के साथ जटिल तर्क के लिए Visitor अपरिहार्य रहता है।
3. स्टेट पैटर्न (State)
स्टेट पैटर्न एक ऑब्जेक्ट को आंतरिक स्थिति के आधार पर अपना व्यवहार बदलने की अनुमति देता है। यह बोझिल if-else या switch-case का एक सुरुचिपूर्ण विकल्प है।
Kotlin में, हम स्थितियों को प्रस्तुत करने के लिए sealed क्लास का उपयोग कर सकते हैं। उदाहरण - ऑनलाइन स्टोर में ऑर्डर