पायथन में एडेप्टर डिजाइन पैटर्न

परिचय

RSI एडेप्टर डिजाइन पैटर्न एक लोकप्रिय है संरचनात्मक डिजाइन पैटर्न सॉफ्टवेयर इंजीनियरिंग में उपयोग किया जाता है। यह मार्गदर्शिका यह देखती है कि हम पायथन में एडेप्टर डिज़ाइन पैटर्न को कैसे लागू कर सकते हैं।

डिजाइन पैटर्न्स टेम्पलेट जैसे समाधान हैं - सॉफ्टवेयर विकास में आवर्ती, सामान्य समस्याओं को हल करने के लिए व्यावहारिक रूप से व्यंजन। एडेप्टर पैटर्न एक वास्तविक दुनिया एडेप्टर की अवधारणा पर आधारित है! उदाहरण के लिए, लैपटॉप के चार्जर में अंत में 3-पिन प्लग हो सकता है, लेकिन वॉल सॉकेट केवल 2-पिन सॉकेट हो सकता है। इस सॉकेट में 3-पिन चार्जर प्लग करने के लिए, हमें एक एडेप्टर की आवश्यकता होगी, जो 3-पिन प्लग को स्वीकार करे, और अनुकूलन इंटरफ़ेस में 2 पिन सॉकेट।

एक 2-पिन चार्जर और एक 3-पिन चार्जर है एक ही मूल कार्य (सॉकेट से लैपटॉप तक बिजली का संचालन करें), लेकिन है एक अलग रूप, और कोई भी आसानी से कर सकता है अनुकूलन दूसरे में। जब भी आपके पास एक ही मूल कार्य लेकिन विभिन्न रूपों वाले सॉफ़्टवेयर घटक हों, तो आप एडेप्टर डिज़ाइन पैटर्न लागू कर सकते हैं।

एडेप्टर पैटर्न इस सटीक सिद्धांत का अनुसरण करता है। यह दो असंगत इंटरफेस को प्रत्येक घटक के आंतरिक को संशोधित किए बिना एक साथ काम करने की अनुमति देता है। यह एक इंटरफ़ेस को दूसरे में, बाहरी रूप से अनुकूलित करके प्राप्त किया जाता है।

आइए एडेप्टर पैटर्न की दुनिया में गहराई से गोता लगाने से पहले कुछ बुनियादी शब्दावली देखें:

  • क्लाइंट इंटरफ़ेस: एक इंटरफ़ेस जो उन कार्यों को निर्दिष्ट करता है जिन्हें क्लाइंट को लागू करना चाहिए।
  • ग्राहक: एक वर्ग जो क्लाइंट इंटरफ़ेस को लागू करता है।
  • अनुकूली/सेवा: असंगत वर्ग जिसे क्लाइंट इंटरफ़ेस के साथ सहयोग करने की आवश्यकता है।
  • अनुकूलक: वह वर्ग जो सेवा और ग्राहक के बीच सहयोग को संभव बनाता है।

विभिन्न प्रकार के एडेप्टर पैटर्न

एडेप्टर डिज़ाइन पैटर्न को दो अलग-अलग तरीकों से लागू किया जा सकता है:

ऑब्जेक्ट एडॉप्टर

इस पद्धति के साथ, एडेप्टर वर्ग क्लाइंट इंटरफ़ेस से विधियों को लागू करता है। इस प्रकार, क्लाइंट ऑब्जेक्ट और एडेप्टर ऑब्जेक्ट एक दूसरे के साथ संगत हैं। सेवा वस्तु रूपों a has-a एडेप्टर ऑब्जेक्ट के साथ संबंध यानी सर्विस ऑब्जेक्ट एडेप्टर ऑब्जेक्ट से संबंधित है।

हम जानते हैं कि सेवा वर्ग क्लाइंट के साथ संगत नहीं है। एडेप्टर क्लास उस ऑब्जेक्ट के साथ खुद को इंस्टेंट करके सर्विस ऑब्जेक्ट के चारों ओर लपेटता है। अब, सर्विस ऑब्जेक्ट को एडेप्टर ऑब्जेक्ट के माध्यम से एक्सेस किया जा सकता है, जिससे क्लाइंट इसके साथ इंटरैक्ट कर सकता है।

हम सभी आधुनिक प्रोग्रामिंग भाषाओं में ऑब्जेक्ट एडेप्टर को लागू कर सकते हैं।

क्लास एडॉप्टर

इस विधि के साथ, एडॉप्टर में एक is-a सेवा वर्ग के साथ संबंध। इस परिदृश्य में, एडेप्टर क्लाइंट द्वारा आवश्यक विधियों को लागू करता है, लेकिन यह कई एडेप्टीज़ से विरासत में मिलता है, जिससे यह सीधे उनके असंगत कार्यों को कॉल करने की क्षमता देता है। इस भिन्नता के साथ सबसे बड़ी कमी यह है कि हम इसका उपयोग केवल उन प्रोग्रामिंग भाषाओं में कर सकते हैं जो कक्षाओं के एकाधिक वंशानुक्रम का समर्थन करती हैं।

पायथन में एडेप्टर डिज़ाइन पैटर्न का कार्यान्वयन

नीचे दिए गए भाग में, हम विशेष रूप से का उपयोग करते हुए, पायथन में एडेप्टर डिज़ाइन पैटर्न को लागू करेंगे वस्तु अनुकूलक भिन्नता. खंड को दो भागों में बांटा गया है। सबसे पहले, हम उस वातावरण का निर्माण करेंगे जहां एडेप्टर पैटर्न का उपयोग किया जाना चाहिए। यह स्पष्ट रूप से देखना महत्वपूर्ण है कि यह पैटर्न कुछ सॉफ़्टवेयर समस्याओं को कैसे हल कर सकता है। दूसरा खंड समस्या को हल करने के लिए एडेप्टर का उपयोग करेगा।

कक्षाओं के बीच असंगति मुद्दा

आइए संगतता समस्या को देखें जब क्लाइंट और सेवा वर्ग विभिन्न कार्यक्षमताओं को लागू करते हैं। निम्न विधियों के साथ क्लाइंट क्लास बनाएं और इसे एक फ़ोल्डर में सहेजें: car.py:

import random

class Car:
    def __init__(self):
        self.generator = random.Random()

    def accelerate(self):
        random_num = self.generator.randint(50, 100)
        speed = random_num
        print(f"The speed of the car is {speed} mph")

    def apply_brakes(self):
        random_num = self.generator.randint(20, 40)
        speed = random_num
        print(f"The speed of the car is {speed} mph after applying the brakes")

    def assign_driver(self, driver_name):
        print(f"{driver_name} is driving the car")

यहाँ, हमने एक बनाया है Car तीन विधियों के साथ वर्ग accelerate(), apply_brakes() और assign_driver(). हमने आयात किया random मॉड्यूल और इसका उपयोग संख्याओं को उत्पन्न करने के लिए किया जाता है जो ब्रेक लगाने और तेज करने के बाद कार की गति निर्धारित करते हैं। assign_driver() विधि कार चालक का नाम प्रदर्शित करती है।

इसके बाद, हमें एक सेवा या अनुकूली वर्ग बनाना होगा जो ग्राहक वर्ग के साथ सहयोग करना चाहता है Car. इस तरह से एक मोटरसाइकिल क्लास बनाएं और इसे अपने फोल्डर में इस तरह सेव करें motorcycle.py:

import random

class Motorcycle:
    def __init__(self):
        self.generator = random.Random()

    def rev_throttle(self):
        random_num = self.generator.randint(50, 100)
        speed = random_num
        print(f"The speed of the motorcycle is {speed} mph")

    def pull_brake_lever(self):
        random_num = self.generator.randint(20, 40)
        speed = random_num
        print(
            f"The speed of the motorcycle is {speed} mph after applying the brakes")

    def assign_rider(self, rider_name):
        print(f"{rider_name} is riding the motorcycle")  

एक सेवा वर्ग, Motorcycle ऊपर तीन तरीकों से बनाया गया है rev_throttle(), pull_brake_lever(), तथा assign_rider(). समान कार्यक्षमता के बावजूद सेवा और क्लाइंट वर्ग के तरीकों के बीच अंतर पर ध्यान दें। accelerator() विधि कार की गति को बढ़ाती है जबकि rev_throttle() विधि मोटरसाइकिल की गति को बढ़ाती है। वैसे ही, apply_brakes() और pull_brake_lever() संबंधित वाहनों में ब्रेक लगाता है। अंततः assign_driver() और assign_rider() तरीके वाहन ऑपरेटर को असाइन करते हैं।

अगला, आइए इन विभिन्न विधियों तक पहुँचने के लिए एक वर्ग बनाएँ। सबसे पहले, एक जोड़ें __init.py__ उसी फोल्डर में जिसे आपने बनाया है car.py और motorcycle.py:

touch __init__.py

अब निम्न कोड को एक नई फाइल में जोड़ें drive.py:

from car import Car
from motorcycle import Motorcycle
import traceback

if __name__ == '__main__':
    car = Car()
    bike = Motorcycle()

    print("The Motorcyclen")
    bike.assign_rider("Subodh")
    bike.rev_throttle()
    bike.pull_brake_lever()
    print("n")

    print("The Carn")
    car.assign_driver("Sushant")
    car.accelerate()
    car.apply_brakes()
    print("n")

    print("Attempting to call client methods with the service objectn")

    try:
        bike.assign_driver("Robert")
        bike.accelerate()
        bike.apply_brakes()
    except AttributeError:
        print("Oops! bike object cannot access car methods")
        traceback.print_exc()

यह स्क्रिप्ट जो हमारे क्लाइंट और सर्विस ऑब्जेक्ट बनाती है। हम पहले आयात करते हैं Car और Motorcycle कक्षाएं और उनके साथ ऑब्जेक्ट बनाएं। फिर हम से विधियों का आह्वान करते हैं bike वस्तु (Motorcycle कक्षा)। इसके बाद, हम के तरीकों का आह्वान करते हैं car वस्तु (Car कक्षा)। निष्पादित होने पर, अब तक उल्लिखित सभी कोड काम करेंगे।

हालाँकि, एक अपवाद तब उठाया जाता है जब हम के तरीकों को लागू करने का प्रयास करते हैं Car के साथ कक्षा bike वस्तु। जब हम इस स्क्रिप्ट को चलाते हैं:

The Motorcycle

Subodh is riding the motorcycle
The speed of the motorcycle is 91 mph
The speed of the motorcycle is 37 mph after applying the brakes


The Car

Sushant is driving the car
The speed of the car is 59 mph
The speed of the car is 33 mph after applying the brakes


Attempting to call client methods with the service object

Oops! bike object cannot access car methods
Traceback (most recent call last):
  File "drive.py", line 24, in 
    bike.assign_driver("Robert")
AttributeError: 'Motorcycle' object has no attribute 'assign_driver'

इस मामले में, हम संशोधित कर सकते हैं Motorcycle वर्ग या drive.py सही तरीकों का उपयोग करने के लिए स्क्रिप्ट। हालांकि, कई मामलों में, हमारे पास क्लाइंट या सेवा वर्ग के स्रोत कोड तक पहुंच नहीं हो सकती है। इसके अलावा, यह एक साधारण उदाहरण है। बड़े ग्राहकों और सेवाओं के साथ, यदि हम अन्य प्रणालियों के साथ संगतता को तोड़ते हैं, तो उनमें से किसी को भी रिफैक्टर करना संभव नहीं है।

इसके बजाय, हम अपने क्लाइंट कोड और हमारे सर्विस ऑब्जेक्ट के बीच संगतता अंतर को पाटने के लिए एडेप्टर का उपयोग कर सकते हैं।

असंगति समस्या को हल करने के लिए एडेप्टर का उपयोग करना

एक नई फ़ाइल में, motorcycle_adapter.py, निम्न वर्ग जोड़ें:

class MotorcycleAdapter:

    def __init__(self, motorcycle):
        self.motorcycle = motorcycle

    def accelerate(self):
        self.motorcycle.rev_throttle()

    def apply_brakes(self):
        self.motorcycle.pull_brake_lever()

    def assign_driver(self, name):
        self.motorcycle.assign_rider(name)

हम बनाया एक MotorcycleAdapter क्लास, जो खुद को सर्विस ऑब्जेक्ट के साथ इंस्टेंट करता है (motorcycle) एडेप्टर क्लाइंट विधियों को लागू करता है जो हैं accelerate(), apply_brakes() और assign_driver(). के शरीर के अंदर accelerate() विधि, हमने उपयोग किया है motorcycle कॉल करने के लिए सेवा वस्तु का उदाहरण rev_throttle() सेवा विधि। इसी तरह, अन्य विधियाँ संगत विधियों का उपयोग करती हैं Motorcycle वर्ग.

अब, चलिए अपडेट करते हैं drive.py इसलिए हम एडेप्टर का उपयोग कर सकते हैं try/except खंड मैथा:

from car import Car
from motorcycle import Motorcycle
from motorcycle_adapter import MotorcycleAdapter 
import traceback

if __name__ == '__main__':
    car = Car()
    bike = Motorcycle()
    bike_adapter = MotorcycleAdapter(bike) 

    ...

    try:
        print("Attempting to call client methods with the service object using an adaptern")
        bike_adapter.assign_driver("Robert")
        bike_adapter.accelerate()
        bike_adapter.apply_brakes()
    except AttributeError:
        print("Oops! bike object cannot access car methods")
        traceback.print_exc()

यहाँ,bike_adapter की वस्तु है MotorcycleAdapter कक्षा। हमने आपूर्ति की bike पर आपत्ति MotorcycleAdapter क्लास' कंस्ट्रक्टर। इस स्क्रिप्ट को निष्पादित करने से हमें निम्नलिखित आउटपुट मिलते हैं:

सर्वोत्तम प्रथाओं, उद्योग-स्वीकृत मानकों और शामिल चीट शीट के साथ, Git सीखने के लिए व्यावहारिक मार्गदर्शिका देखें। Googling Git कमांड को रोकें और वास्तव में सीखना यह!

The Motorcycle

Subodh is riding the motorcycle
The speed of the motorcycle is 88 mph
The speed of the motorcycle is 35 mph after applying the brakes


The Car

Sushant is driving the car
The speed of the car is 91 mph
The speed of the car is 24 mph after applying the brakes


Attempting to call client methods with the service object

Attempting to call client methods with the service object using an adapter

Robert is riding the motorcyle
The speed of the motorcycle is 67 mph
The speed of the motorcycle is 25 mph after applying the brakes

अंतर्निहित को समायोजित किए बिना Motorcycle कक्षा, हम इसे a . की तरह काम करने के लिए प्राप्त कर सकते हैं Car एक एडेप्टर का उपयोग करना!

एडेप्टर डिज़ाइन पैटर्न के पेशेवरों और विपक्ष

एडेप्टर पैटर्न के फायदे हैं:

  • हम एडेप्टर क्लास और क्लाइंट क्लास के बीच कम युग्मन प्राप्त कर सकते हैं।
  • हम एप्लिकेशन में कई सेवा वर्गों को शामिल करने के लिए एडेप्टर वर्ग का पुन: उपयोग कर सकते हैं।
  • हम क्लाइंट कोड में हस्तक्षेप किए बिना कई एडेप्टर पेश करके प्रोग्राम के लचीलेपन को बढ़ा सकते हैं

एडेप्टर पैटर्न के नुकसान हैं:

  • एडेप्टर क्लास और सर्विस क्लास को जोड़ने के साथ प्रोग्राम की जटिलता बढ़ जाती है।
  • कार्यक्रम में ओवरहेड की वृद्धि हुई है क्योंकि अनुरोध एक वर्ग से दूसरे वर्ग में अग्रेषित किए जाते हैं।
  • एडेप्टर पैटर्न (क्लास एडॉप्टर) कई इनहेरिटेंस का उपयोग करता है, जो सभी प्रोग्रामिंग भाषाओं का समर्थन नहीं कर सकता है।

निष्कर्ष

इस लेख में, हमने एडेप्टर डिज़ाइन पैटर्न, इसके प्रकारों और उनके द्वारा हल की जाने वाली समस्याओं के बारे में सीखा। हमने पायथन में एडेप्टर पैटर्न लागू किया है ताकि हम एक के साथ बातचीत कर सकें Motorcycle वस्तु, जैसे a Car एडॉप्टर का उपयोग करके ऑब्जेक्ट करें ताकि प्रत्येक वर्ग का इंटरफ़ेस न बदले।

समय टिकट:

से अधिक स्टैकब्यूज