खोज…


परिचय

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

रणनीति पैटर्न

इस डिज़ाइन पैटर्न को रणनीति पैटर्न कहा जाता है। इसका उपयोग एल्गोरिदम के एक परिवार को परिभाषित करने, प्रत्येक को एनकैप्सुलेट करने और उन्हें विनिमेय बनाने के लिए किया जाता है। रणनीति डिजाइन पैटर्न एक एल्गोरिथ्म का उपयोग करने वाले ग्राहकों से स्वतंत्र रूप से भिन्न होता है।

उदाहरण के लिए, जानवर कई अलग-अलग तरीकों से "चल" सकते हैं। घूमना एक रणनीति मानी जा सकती है जो विभिन्न प्रकार के जानवरों द्वारा कार्यान्वित की जाती है:

from types import MethodType


class Animal(object):
    
    def __init__(self, *args, **kwargs):
        self.name = kwargs.pop('name', None) or 'Animal'
        if kwargs.get('walk', None):
            self.walk = MethodType(kwargs.pop('walk'), self)

    def walk(self):
        """
        Cause animal instance to walk
        
        Walking funcionallity is a strategy, and is intended to
        be implemented separately by different types of animals.
        """
        message = '{} should implement a walk method'.format(
            self.__class__.__name__)
        raise NotImplementedError(message)


# Here are some different walking algorithms that can be used with Animal
def snake_walk(self):
    print('I am slithering side to side because I am a {}.'.format(self.name))

def four_legged_animal_walk(self):
    print('I am using all four of my legs to walk because I am a(n) {}.'.format(
        self.name))

def two_legged_animal_walk(self):
    print('I am standing up on my two legs to walk because I am a {}.'.format(
        self.name))

इस उदाहरण को चलाने से निम्नलिखित आउटपुट उत्पन्न होंगे:

generic_animal = Animal()
king_cobra = Animal(name='King Cobra', walk=snake_walk)
elephant = Animal(name='Elephant', walk=four_legged_animal_walk)
kangaroo = Animal(name='Kangaroo', walk=two_legged_animal_walk)

kangaroo.walk()
elephant.walk()
king_cobra.walk()
# This one will Raise a NotImplementedError to let the programmer
# know that the walk method is intended to be used as a strategy.
generic_animal.walk()

    # OUTPUT:
    #
    # I am standing up on my two legs to walk because I am a Kangaroo.
    # I am using all four of my legs to walk because I am a(n) Elephant.
    # I am slithering side to side because I am a King Cobra.
    # Traceback (most recent call last):
    #   File "./strategy.py", line 56, in <module>
    #     generic_animal.walk()
    #   File "./strategy.py", line 30, in walk
    #     raise NotImplementedError(message)
    # NotImplementedError: Animal should implement a walk method 

ध्यान दें कि C ++ या Java जैसी भाषाओं में, यह पैटर्न एक एब्स्ट्रैक्ट क्लास या एक इंटरफ़ेस का उपयोग करके कार्यान्वित किया जाता है, जिसमें एए रणनीति को परिभाषित किया जाता है। पायथन में, यह केवल कुछ कार्यों को बाहरी रूप से परिभाषित करने के लिए अधिक समझ में आता है जो कि types.MethodType का उपयोग करके एक वर्ग में गतिशील रूप से जोड़ा जा सकता है।

डिजाइन पैटर्न और सिंगलटन पैटर्न का परिचय

डिजाइन पैटर्न सॉफ्टवेयर डिजाइन में commonly occurring problems समाधान प्रदान करते हैं। डिजाइन पैटर्न पहले GoF(Gang of Four) द्वारा पेश किए गए थे, जहां उन्होंने सामान्य पैटर्न को उन समस्याओं के रूप में वर्णित किया जो बार-बार होती हैं और उन समस्याओं का समाधान करते हैं।

डिज़ाइन पैटर्न में चार आवश्यक तत्व होते हैं:

  1. The pattern name एक हैंडल है जिसका उपयोग हम एक डिजाइन समस्या, उसके समाधान और एक शब्द या दो में परिणाम का वर्णन करने के लिए कर सकते हैं।
  2. पैटर्न को लागू करने के लिए The problem वर्णन है।
  3. The solution उन तत्वों का वर्णन करता है जो डिजाइन, उनके संबंधों, जिम्मेदारियों और सहयोगों को बनाते हैं।
  4. The consequences पैटर्न को लागू करने के परिणाम और व्यापार-बंद हैं।

डिजाइन पैटर्न के लाभ:

  1. वे कई परियोजनाओं में पुन: प्रयोज्य हैं।
  2. समस्याओं का वास्तु स्तर हल किया जा सकता है
  3. वे समय-परीक्षण और अच्छी तरह से सिद्ध हैं, जो डेवलपर्स और आर्किटेक्ट का अनुभव है
  4. उनके पास विश्वसनीयता और निर्भरता है

डिजाइन पैटर्न को तीन श्रेणियों में वर्गीकृत किया जा सकता है:

  1. रचनात्मक पैटर्न
  2. संरचनात्मक पैटर्न
  3. व्यवहार पैटर्न

Creational Pattern - वे इस बात से चिंतित हैं कि ऑब्जेक्ट कैसे बनाया जा सकता है और वे ऑब्जेक्ट निर्माण के विवरण को अलग करते हैं।

Structural Pattern - वे कक्षाओं और वस्तुओं की संरचना को डिज़ाइन करते हैं ताकि वे बड़े परिणाम प्राप्त कर सकें।

Behavioral Pattern - वे वस्तुओं के बीच बातचीत और वस्तुओं की जिम्मेदारी से संबंधित हैं।

सिंगलटन पैटर्न :

यह एक प्रकार का creational pattern जो किसी दिए गए प्रकार के केवल एक और एक ऑब्जेक्ट के लिए एक तंत्र प्रदान करता है और पहुंच का एक वैश्विक बिंदु प्रदान करता है।

उदाहरण के लिए, सिंगलटन का उपयोग डेटाबेस ऑपरेशंस में किया जा सकता है, जहाँ हम डेटा को बनाए रखने के लिए डेटाबेस ऑब्जेक्ट चाहते हैं।

कार्यान्वयन

हम सिंगलटन का केवल एक उदाहरण बनाकर और फिर से उसी वस्तु की सेवा करके पायथन में सिंगलटन पैटर्न को लागू कर सकते हैं।

class Singleton(object):
    def __new__(cls):
        # hasattr method checks if the class object an instance property or not.
        if not hasattr(cls, 'instance'):
            cls.instance = super(Singleton, cls).__new__(cls)
        return cls.instance

s = Singleton()
print ("Object created", s)

s1 = Singleton()
print ("Object2 created", s1)

आउटपुट:

('Object created', <__main__.Singleton object at 0x10a7cc310>)
('Object2 created', <__main__.Singleton object at 0x10a7cc310>)

ध्यान दें कि C ++ या Java जैसी भाषाओं में, इस पैटर्न को कंस्ट्रक्टर को निजी बनाकर और स्टैटिक विधि से बनाया जाता है जो ऑब्जेक्ट इनिशियलाइज़ेशन करता है। इस तरह, पहली कॉल पर एक ऑब्जेक्ट बन जाता है और उसके बाद क्लास एक ही ऑब्जेक्ट देता है। लेकिन पायथन में, हमारे पास निजी निर्माणकर्ता बनाने का कोई तरीका नहीं है।

फैक्टरी पैटर्न

फैक्ट्री पैटर्न भी एक Creational pattern । शब्द factory मतलब है कि एक वर्ग अन्य प्रकार की वस्तुओं को बनाने के लिए जिम्मेदार है। एक वर्ग है जो एक कारखाने के रूप में कार्य करता है जिसमें वस्तुओं और इसके साथ जुड़े तरीके हैं। क्लाइंट कुछ मापदंडों के साथ तरीकों को कॉल करके एक ऑब्जेक्ट बनाता है और फैक्ट्री वांछित प्रकार का ऑब्जेक्ट बनाता है और क्लाइंट को वापस कर देता है।

from abc import ABCMeta, abstractmethod

class Music():
    __metaclass__ = ABCMeta
    @abstractmethod
    def do_play(self):
        pass

class Mp3(Music):
    def do_play(self):
        print ("Playing .mp3 music!")
    
class Ogg(Music):
    def do_play(self):
        print ("Playing .ogg music!")
    
class MusicFactory(object):
    def play_sound(self, object_type):
        return eval(object_type)().do_play()
    
if __name__ == "__main__":
    mf = MusicFactory()
    music = input("Which music you want to play Mp3 or Ogg")
    mf.play_sound(music)

आउटपुट:

Which music you want to play Mp3 or Ogg"Ogg"
Playing .ogg music!

MusicFactory यहाँ का कारखाना वर्ग है जो पसंद किए गए उपयोगकर्ता के आधार पर टाइप Mp3 या Ogg का एक ऑब्जेक्ट बनाता है।

प्रतिनिधि

प्रॉक्सी ऑब्जेक्ट का उपयोग अक्सर किसी अन्य ऑब्जेक्ट तक पहरा देने को सुनिश्चित करने के लिए किया जाता है, जो आंतरिक व्यावसायिक तर्क हम सुरक्षा आवश्यकताओं के साथ प्रदूषित नहीं करना चाहते हैं।

मान लीजिए कि हम गारंटी देना चाहते हैं कि विशिष्ट अनुमतियों का केवल उपयोगकर्ता ही संसाधन तक पहुँच सकता है।

प्रॉक्सी परिभाषा: (यह सुनिश्चित करता है कि केवल वे उपयोगकर्ता जो वास्तव में आरक्षण देख सकते हैं उपभोक्ता आरक्षण_ सेवा में सक्षम होंगे)

from datetime import date
from operator import attrgetter

class Proxy:
    def __init__(self, current_user, reservation_service):
        self.current_user = current_user
        self.reservation_service = reservation_service

    def highest_total_price_reservations(self, date_from, date_to, reservations_count):
        if self.current_user.can_see_reservations:
            return self.reservation_service.highest_total_price_reservations(
                date_from,
                date_to,
                reservations_count
              )
        else:
            return []

#Models and ReservationService:

class Reservation:
    def __init__(self, date, total_price):
        self.date = date
        self.total_price = total_price

class ReservationService:
    def highest_total_price_reservations(self, date_from, date_to, reservations_count):
        # normally it would be read from database/external service
        reservations = [
            Reservation(date(2014, 5, 15), 100),
            Reservation(date(2017, 5, 15), 10),
            Reservation(date(2017, 1, 15), 50)
        ]

        filtered_reservations = [r for r in reservations if (date_from <= r.date <= date_to)]

        sorted_reservations = sorted(filtered_reservations, key=attrgetter('total_price'), reverse=True)

        return sorted_reservations[0:reservations_count]


class User:
    def __init__(self, can_see_reservations, name):
        self.can_see_reservations = can_see_reservations
        self.name = name

#Consumer service:

class StatsService:
    def __init__(self, reservation_service):
        self.reservation_service = reservation_service

    def year_top_100_reservations_average_total_price(self, year):
        reservations = self.reservation_service.highest_total_price_reservations(
            date(year, 1, 1),
            date(year, 12, 31),
            1
        )

        if len(reservations) > 0:
            total = sum(r.total_price for r in reservations)

            return total / len(reservations)
        else:
            return 0

#Test:
def test(user, year):
    reservations_service = Proxy(user, ReservationService())
    stats_service = StatsService(reservations_service)
    average_price = stats_service.year_top_100_reservations_average_total_price(year)
    print("{0} will see: {1}".format(user.name, average_price))

test(User(True, "John the Admin"), 2017)
test(User(False, "Guest"),         2017)

लाभ
  • जब एक्सेस प्रतिबंध बदले जाते हैं, तो हम ReservationService में किसी भी बदलाव से बचते हैं।
  • हम व्यापार से संबंधित डेटा (मिश्रण नहीं कर रहे हैं date_from , date_to , reservations_count सेवा में डोमेन असंबंधित अवधारणाओं (उपयोगकर्ता अनुमतियों) के साथ)।
  • उपभोक्ता ( StatsService ) अनुमति संबंधी तर्क से भी मुक्त है

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


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow