एडेप्टर पैटर्न: Difference between revisions

From Vigyanwiki
No edit summary
 
(One intermediate revision by one other user not shown)
Line 524: Line 524:


{{Design Patterns Patterns}}
{{Design Patterns Patterns}}
[[Category: सॉफ्टवेयर डिजाइन पैटर्न]] [[Category: जावा कोड उदाहरण के साथ लेख]]


 
[[Category:Articles with example Java code]]
 
[[Category:Collapse templates]]
[[Category: Machine Translated Page]]
[[Category:Commons category link is locally defined]]
[[Category:Created On 24/05/2023]]
[[Category:Created On 24/05/2023]]
[[Category:Vigyan Ready]]
[[Category:Lua-based templates]]
[[Category:Machine Translated Page]]
[[Category:Navigational boxes| ]]
[[Category:Navigational boxes without horizontal lists]]
[[Category:Pages with script errors]]
[[Category:Pages with syntax highlighting errors]]
[[Category:Sidebars with styles needing conversion]]
[[Category:Template documentation pages|Documentation/doc]]
[[Category:Templates Vigyan Ready]]
[[Category:Templates generating microformats]]
[[Category:Templates that add a tracking category]]
[[Category:Templates that are not mobile friendly]]
[[Category:Templates that generate short descriptions]]
[[Category:Templates using TemplateData]]
[[Category:Wikipedia metatemplates]]
[[Category:जावा कोड उदाहरण के साथ लेख]]
[[Category:सॉफ्टवेयर डिजाइन पैटर्न]]

Latest revision as of 09:10, 13 June 2023

सॉफ्टवेयर इंजीनियरिंग में, एडेप्टर पैटर्न सॉफ्टवेयर डिजाइन पैटर्न है (जिसे आवरण समारोह के रूप में भी जाना जाता है, डेकोरेटर पैटर्न के साथ साझा किया गया वैकल्पिक नामकरण), जो वर्तमान वर्ग (कंप्यूटर विज्ञान) के इंटरफ़ेस (कंप्यूटर विज्ञान) को दूसरे इंटरफ़ेस के रूप में उपयोग करने की अनुमति देता है।[1] इसका उपयोग अधिकांशतः वर्तमान कक्षाओं को उनके स्रोत कोड को संशोधित किए बिना दूसरों के साथ कार्य करने के लिए किया जाता है।

उदाहरण एडेप्टर है, जो एक्सएमएल दस्तावेज़ के दस्तावेज़ ऑब्जेक्ट मॉडल के इंटरफ़ेस को ट्री संरचना में परिवर्तित करता है, जिसे प्रदर्शित किया जा सकता है।

सिंहावलोकन

एडॉप्टर[2] डिज़ाइन पैटर्न तेईस जाने-माने गैंग ऑफ़ फोर (सॉफ़्टवेयर) डिज़ाइन पैटर्न में से एक है, जो वर्णन करता है कि लचीले और पुन: प्रयोज्य ऑब्जेक्ट-ओरिएंटेड सॉफ़्टवेयर को डिज़ाइन करने के लिए आवर्ती डिज़ाइन समस्याओं को कैसे हल किया जाए, अर्थात् ऐसी वस्तुएँ जिन्हें प्रयुक्त करना, बदलना, परीक्षण, और पुन: उपयोग करना सरल है।

एडॉप्टर डिज़ाइन पैटर्न समस्याओं को हल करता है जैसे:[3]

  • वर्ग का पुन: उपयोग कैसे किया जा सकता है, जिसमें क्लाइंट की आवश्यकता वाला इंटरफ़ेस नहीं है?
  • असंगत इंटरफेस वाली कक्षाएं एक साथ कैसे कार्य कर सकती हैं?
  • वर्ग के लिए वैकल्पिक इंटरफ़ेस कैसे प्रदान किया जा सकता है?

अधिकांशतः (पहले से उपस्थित) वर्ग का पुन: उपयोग नहीं किया जा सकता है क्योंकि इसका इंटरफ़ेस इंटरफ़ेस क्लाइंट की आवश्यकता के अनुरूप नहीं होता है।

एडेप्टर डिज़ाइन पैटर्न बताता है कि ऐसी समस्याओं को कैसे हल किया जाए:

  • अलग adapter वर्ग को परिभाषित करें जो वर्ग (adaptee) के (असंगत) इंटरफ़ेस को दूसरे इंटरफ़ेस (target) क्लाइंट में परिवर्तित करता है।
  • (पुन: उपयोग) कक्षाओं के साथ कार्य करने के लिए adapter के माध्यम से कार्य करें जिसमें आवश्यक इंटरफ़ेस नहीं है।

इस पैटर्न में मुख्य विचार अलग adapter के माध्यम से कार्य करना है जो इसे परिवर्तित करे बिना (पहले से उपस्थित) वर्ग के इंटरफ़ेस को अनुकूलित करता है।

ग्राहक यह नहीं जानते हैं कि वे target वर्ग के साथ सीधे कार्य करते हैं या adapter के माध्यम से उस वर्ग के साथ कार्य करते हैं जिसमें target इंटरफ़ेस नहीं है।

नीचे यूएमएल क्लास डायग्राम भी देखें।

परिभाषा

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

उपयोग

एडेप्टर का उपयोग तब किया जा सकता है, जब रैपर को विशेष इंटरफ़ेस का सम्मान करना चाहिए और बहुरूपता (कंप्यूटर विज्ञान) व्यवहार का समर्थन करना चाहिए। वैकल्पिक रूप से, डेकोरेटर पैटर्न रन-टाइम पर इंटरफ़ेस के व्यवहार को जोड़ना या परिवर्तित करना संभव बनाता है, और जब किसी अंतर्निहित वस्तु के लिए आसान या सरल इंटरफ़ेस वांछित होता है, तो अग्रभाग पैटर्न का उपयोग किया जाता है।[4]

प्रतिरूप आशय
एडॉप्टर या रैपर इंटरफ़ेस को दूसरे में परिवर्तित करता है, जिससे यह ग्राहक की अपेक्षा से मेल खाता हो
डेकोरेटर मूल कोड को लपेटकर गतिशील रूप से इंटरफ़ेस में उत्तरदायिता जोड़ता है
प्रतिनिधि मंडल समर्थन "विरासत पर रचना"
अग्रभाग सरलीकृत इंटरफ़ेस प्रदान करता है


संरचना

यूएमएल वर्ग आरेख

एडेप्टर डिज़ाइन पैटर्न के लिए नमूना यूएमएल वर्ग आरेख।[5]

उपरोक्त यूएमएल वर्ग आरेख में, जिस client वर्ग को target इंटरफ़ेस की आवश्यकता होती है, वह सीधे adaptee वर्ग का पुन: उपयोग नहीं कर सकता क्योंकि इसका इंटरफ़ेस target इंटरफ़ेस के अनुरूप नहीं होता है। इसके अतिरिक्त, client adapter वर्ग के माध्यम से कार्य करता है जो adaptee के संदर्भ में target इंटरफ़ेस को प्रयुक्त करता है:

  • object adapter विधि रन-टाइम (adaptee.specificOperation()) पर adaptee ऑब्जेक्ट को प्रत्यायोजित करके target इंटरफ़ेस को प्रयुक्त करता है।
  • class adapter विधि कंपाइल-टाइम (specificOperation()) पर adaptee क्लास से इनहेरिट करके target इंटरफेस को प्रयुक्त करता है।

ऑब्जेक्ट एडेप्टर पैटर्न

इस एडॉप्टर पैटर्न में, एडेप्टर में उस वर्ग का उदाहरण होता है जिसे वह लपेटता है। इस स्थिति में, एडेप्टर लिपटे ऑब्जेक्ट की आवृत्ति के लिए कॉल करता है।

यूनिफाइड मॉडलिंग भाषा में व्यक्त ऑब्जेक्ट एडेप्टर पैटर्न
लेपस3 में व्यक्त वस्तु अनुकूलक पैटर्न

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

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

यूनिफाइड मॉडलिंग भाषा में व्यक्त क्लास एडेप्टर पैटर्न।
लेपस3 में व्यक्त क्लास अडैप्टर पैटर्न

रनटाइम एडेप्टर पैटर्न का एक और रूप

संकलन समय समाधान से प्रेरणा

यह classA के लिए कुछ डेटा के साथ classB की आपूर्ति करने के लिए वांछित है, आइए हम कुछ String डेटा मान लें। संकलन समय समाधान है:

classB.setStringData(classA.getStringData());

चूँकि, मान लीजिए कि स्ट्रिंग डेटा का प्रारूप विविध होना चाहिए। संकलन समय समाधान वंशानुक्रम का उपयोग करना है:

public class Format1ClassA extends ClassA {
    @Override
    public String getStringData() {
        return format(toString());
    }
}

और संभवतया फैक्टरी पैटर्न के माध्यम से रनटाइम पर सही स्वरूपण ऑब्जेक्ट बनाएं।

रन-टाइम अनुकूलक समाधान

एडॉप्टर का उपयोग करने वाला समाधान निम्नानुसार आगे बढ़ता है:

  1. मध्यस्थ "प्रदाता" इंटरफ़ेस को परिभाषित करें, और उस प्रदाता इंटरफ़ेस के कार्यान्वयन को लिखें जो इस उदाहरण में डेटा के स्रोत, ClassA को लपेटता है, और उपयुक्त स्वरूपित डेटा को आउटपुट करता है:
    public interface StringProvider {
        public String getStringData();
    }
    
    public class ClassAFormat1 implements StringProvider {
        private ClassA classA = null;
    
        public ClassAFormat1(final ClassA a) {
            classA = a;
        }
    
        public String getStringData() {
            return format(classA.getStringData());
        }
    
        private String format(final String sourceValue) {
            // Manipulate the source string into a format required 
            // by the object needing the source object's data
            return sourceValue.trim();
        }
    }
    
  2. एडेप्टर वर्ग लिखें जो प्रदाता के विशिष्ट कार्यान्वयन को लौटाता है:
    public class ClassAFormat1Adapter extends Adapter {
        public Object adapt(final Object anObject) {
            return new ClassAFormat1((ClassA) anObject);
        }
    }
    
  3. वैश्विक रजिस्ट्री के साथ adapter को पंजीकृत करें, जिससे adapter को रनटाइम पर देखा जा सके:
    AdapterFactory.getInstance().registerAdapter(ClassA.class, ClassAFormat1Adapter.class, "format1");
    
  4. कोड में, जब डेटा को ClassA से ClassB में स्थानांतरित करना हो, तो लिखें:
    Adapter adapter =
        AdapterFactory.getInstance()
            .getAdapterFromTo(ClassA.class, StringProvider.class, "format1");
    StringProvider provider = (StringProvider) adapter.adapt(classA);
    String string = provider.getStringData();
    classB.setStringData(string);
    

    or more concisely:

    classB.setStringData(
        ((StringProvider)
                AdapterFactory.getInstance()
                    .getAdapterFromTo(ClassA.class, StringProvider.class, "format1")
                    .adapt(classA))
            .getStringData());
    
  5. इसमें लाभ देखा जा सकता है, यदि डेटा को दूसरे प्रारूप में स्थानांतरित करने की इच्छा है, तो अलग एडाप्टर/प्रदाता को देखें:
    Adapter adapter =
        AdapterFactory.getInstance()
            .getAdapterFromTo(ClassA.class, StringProvider.class, "format2");
    
  6. और यदि ClassA से डेटा को आउटपुट करने की इच्छा है, जैसे, Class C में छवि डेटा:
    Adapter adapter =
        AdapterFactory.getInstance()
            .getAdapterFromTo(ClassA.class, ImageProvider.class, "format2");
    ImageProvider provider = (ImageProvider) adapter.adapt(classA);
    classC.setImage(provider.getImage());
    
  7. इस तरह, एडेप्टर और प्रदाताओं के उपयोग से ClassB और ClassC द्वारा ClassA में वर्ग पदानुक्रम में परिवर्तन किए बिना कई "विचार" की अनुमति मिलती है। सामान्य तौर पर, यह वस्तुओं के बीच इच्छित डेटा प्रवाह के लिए एक तंत्र की अनुमति देता है जिसे किसी वर्तमान वस्तु पदानुक्रम में वापस लाया जा सकता है।


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

एडेप्टर पैटर्न को प्रयुक्त करते समय, स्पष्टता के लिए, कोई व्यक्ति [ClassName]To[Interface]Adapter को प्रदाता कार्यान्वयन के लिए प्रयुक्त कर सकता है; उदाहरण के लिए, DAOToProviderAdapter। इसमें पैरामीटर के रूप में एडाप्टी क्लास वेरिएबल के साथ कंस्ट्रक्टर विधि होनी चाहिए। यह पैरामीटर [ClassName]To[Interface]Adapter के इंस्टेंस सदस्य को पास किया जाएगा। जब क्लाइंटमेथोड को कॉल किया जाता है, तो उसके पास एडेप्टी इंस्टेंस तक पहुंच होगी जो एडाप्टी के आवश्यक डेटा तक पहुंचने और उस डेटा पर संचालन करने की अनुमति देता है, जो वांछित आउटपुट उत्पन्न करता है।

जावा

interface ILightningPhone {
    void recharge();
    void useLightning();
}

interface IMicroUsbPhone {
    void recharge();
    void useMicroUsb();
}

class Iphone implements ILightningPhone {
    private boolean connector;

    @Override
    public void useLightning() {
        connector = true;
        System.out.println("Lightning connected");
    }

    @Override
    public void recharge() {
        if (connector) {
            System.out.println("Recharge started");
            System.out.println("Recharge finished");
        } else {
            System.out.println("Connect Lightning first");
        }
    }
}

class Android implements IMicroUsbPhone {
    private boolean connector;

    @Override
    public void useMicroUsb() {
        connector = true;
        System.out.println("MicroUsb connected");
    }

    @Override
    public void recharge() {
        if (connector) {
            System.out.println("Recharge started");
            System.out.println("Recharge finished");
        } else {
            System.out.println("Connect MicroUsb first");
        }
    }
}
/* exposing the target interface while wrapping source object */
class LightningToMicroUsbAdapter implements IMicroUsbPhone {
    private final ILightningPhone lightningPhone;

    public LightningToMicroUsbAdapter(ILightningPhone lightningPhone) {
        this.lightningPhone = lightningPhone;
    }

    @Override
    public void useMicroUsb() {
        System.out.println("MicroUsb connected");
        lightningPhone.useLightning();
    }

    @Override
    public void recharge() {
        lightningPhone.recharge();
    }
}

public class AdapterDemo {
    static void rechargeMicroUsbPhone(IMicroUsbPhone phone) {
        phone.useMicroUsb();
        phone.recharge();
    }

    static void rechargeLightningPhone(ILightningPhone phone) {
        phone.useLightning();
        phone.recharge();
    }

    public static void main(String[] args) {
        Android android = new Android();
        Iphone iPhone = new Iphone();

        System.out.println("Recharging android with MicroUsb");
        rechargeMicroUsbPhone(android);

        System.out.println("Recharging iPhone with Lightning");
        rechargeLightningPhone(iPhone);

        System.out.println("Recharging iPhone with MicroUsb");
        rechargeMicroUsbPhone(new LightningToMicroUsbAdapter (iPhone));
    }
}

आउटपुट:

Recharging android with MicroUsb
MicroUsb connected
Recharge started
Recharge finished
Recharging iPhone with Lightning
Lightning connected
Recharge started
Recharge finished
Recharging iPhone with MicroUsb
MicroUsb connected
Lightning connected
Recharge started
Recharge finished

पायथन

"""
Adapter pattern example.
"""
from abc import ABCMeta, abstractmethod

NOT_IMPLEMENTED = "You should implement this."

RECHARGE = ["Recharge started.", "Recharge finished."]

POWER_ADAPTERS = {"Android": "MicroUSB", "iPhone": "Lightning"}

CONNECTED = "{} connected."
CONNECT_FIRST = "Connect {} first."

class RechargeTemplate(metaclass=ABCMeta):

    @abstractmethod
    def recharge(self):
        raise NotImplementedError(NOT_IMPLEMENTED)

class FormatIPhone(RechargeTemplate):
    @abstractmethod
    def use_lightning(self):
        raise NotImplementedError(NOT_IMPLEMENTED)

class FormatAndroid(RechargeTemplate):
    @abstractmethod
    def use_micro_usb(self):
        raise NotImplementedError(NOT_IMPLEMENTED)

class IPhone(FormatIPhone):
    __name__ = "iPhone"

    def __init__(self):
        self.connector = False

    def use_lightning(self):
        self.connector = True
        print(CONNECTED.format(POWER_ADAPTERS[self.__name__]))

    def recharge(self):
        if self.connector:
            for state in RECHARGE:
                print(state)
        else:
            print(CONNECT_FIRST.format(POWER_ADAPTERS[self.__name__]))

class Android(FormatAndroid):
    __name__ = "Android"

    def __init__(self):
        self.connector = False

    def use_micro_usb(self):
        self.connector = True
        print(CONNECTED.format(POWER_ADAPTERS[self.__name__]))

    def recharge(self):
        if self.connector:
            for state in RECHARGE:
                print(state)
        else:
            print(CONNECT_FIRST.format(POWER_ADAPTERS[self.__name__]))

class IPhoneAdapter(FormatAndroid):
    def __init__(self, mobile):
        self.mobile = mobile

    def recharge(self):
        self.mobile.recharge()

    def use_micro_usb(self):
        print(CONNECTED.format(POWER_ADAPTERS["Android"]))
        self.mobile.use_lightning()

class AndroidRecharger:
    def __init__(self):
        self.phone = Android()
        self.phone.use_micro_usb()
        self.phone.recharge()

class IPhoneMicroUSBRecharger:
    def __init__(self):
        self.phone = IPhone()
        self.phone_adapter = IPhoneAdapter(self.phone)
        self.phone_adapter.use_micro_usb()
        self.phone_adapter.recharge()

class IPhoneRecharger:
    def __init__(self):
        self.phone = IPhone()
        self.phone.use_lightning()
        self.phone.recharge()

print("Recharging Android with MicroUSB recharger.")
AndroidRecharger()
print()

print("Recharging iPhone with MicroUSB using adapter pattern.")
IPhoneMicroUSBRecharger()
print()

print("Recharging iPhone with iPhone recharger.")
IPhoneRecharger()


सी#

public interface ILightningPhone
{
	void ConnectLightning();
	void Recharge();
}

public interface IUsbPhone
{
	void ConnectUsb();
	void Recharge();
}

public sealed class AndroidPhone : IUsbPhone
{
	private bool isConnected;
	
	public void ConnectUsb()
	{
		this.isConnected = true;
		Console.WriteLine("Android phone connected.");
	}

	public void Recharge()
	{
		if (this.isConnected)
		{
			Console.WriteLine("Android phone recharging.");
		}
		else
		{
			Console.WriteLine("Connect the USB cable first.");
		}
	}
}

public sealed class ApplePhone : ILightningPhone
{
	private bool isConnected;
	
	public void ConnectLightning()
	{
		this.isConnected = true;
		Console.WriteLine("Apple phone connected.");
	}

	public void Recharge()
	{
		if (this.isConnected)
		{
			Console.WriteLine("Apple phone recharging.");
		}
		else
		{
			Console.WriteLine("Connect the Lightning cable first.");
		}
	}
}

public sealed class LightningToUsbAdapter : IUsbPhone
{
	private readonly ILightningPhone lightningPhone;
	
	private bool isConnected;
	
	public LightningToUsbAdapter(ILightningPhone lightningPhone)
	{
		this.lightningPhone = lightningPhone;
		this.lightningPhone.ConnectLightning();
	}
	
	public void ConnectUsb()
	{
		this.isConnected = true;
		Console.WriteLine("Adapter cable connected.");
	}

	public void Recharge()
	{
		if (this.isConnected)
		{
			this.lightningPhone.Recharge();
		}
		else
		{
			Console.WriteLine("Connect the USB cable first.");
		}
	}
}

public void Main()
{
	ILightningPhone applePhone = new ApplePhone();
	IUsbPhone adapterCable = new LightningToUsbAdapter(applePhone);
	adapterCable.ConnectUsb();
	adapterCable.Recharge();
}


आउटपुट:

Apple phone connected.
Adapter cable connected.
Apple phone recharging.


यह भी देखें

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

संदर्भ

  1. 1.0 1.1 Freeman, Eric; Freeman, Elisabeth; Sierra, Kathy; Bates, Bert (2004). Head First Design Patterns. O'Reilly Media. p. 244. ISBN 978-0-596-00712-6. OCLC 809772256. Archived from the original (paperback) on 2013-05-04. Retrieved 2013-04-30.
  2. Gamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley. pp. 139ff. ISBN 0-201-63361-2.
  3. "The Adapter design pattern - Problem, Solution, and Applicability". w3sDesign.com. Retrieved 2017-08-12.
  4. Freeman, Eric; Freeman, Elisabeth; Sierra, Kathy; Bates, Bert (2004). Hendrickson, Mike; Loukides, Mike (eds.). Head First Design Patterns (paperback). Vol. 1. O'Reilly Media. pp. 243, 252, 258, 260. ISBN 978-0-596-00712-6. Retrieved 2012-07-02.
  5. "The Adapter design pattern - Structure and Collaboration". w3sDesign.com. Retrieved 2017-08-12.