وبلاگ رسانگار
با ما حرفه ای باشید

سرور مجازی NVMe

ایجاد یک Singleton در پایتون

0 37
زمان لازم برای مطالعه: 5 دقیقه


معرفی

در بین تمام الگوهای طراحی، الگوی Singleton جایگاه منحصر به فردی دارد. این ساده است، اما اغلب به اشتباه درک می شود. در این بایت، ما سعی خواهیم کرد الگوی Singleton را توضیح دهیم، اصول اصلی آن را درک کنیم و روش پیاده سازی آن را در پایتون بیاموزیم. ما همچنین چگونگی ایجاد یک سینگلتون با استفاده از دکوراتور را بررسی خواهیم کرد.

الگوی سینگلتون

الگوی Singleton یک الگوی طراحی است که نمونه سازی یک کلاس را به یک نمونه محدود می کند. این زمانی مفید است که دقیقاً یک شیء برای هماهنگ کردن اقدامات در سراسر سیستم مورد نیاز باشد. این مفهوم گاهی به سیستم‌هایی تعمیم می‌یابد که وقتی فقط یک شی وجود دارد کارآمدتر عمل می‌کنند یا نمونه‌سازی را به تعداد معینی از اشیا محدود می‌کنند.

الگوی سینگلتون بخشی از الگوهای طراحی باند چهار است و در دسته الگوهای آفرینشی قرار می گیرد. الگوهای خلاقانه با مکانیسم های خلق اشیا سروکار دارند و سعی می کنند اشیا را به شیوه ای مناسب با موقعیت خلق کنند.

توجه داشته باشید: الگوی سینگلتون به دلیل پتانسیل استفاده نادرست از سوی برخی، یک ضد الگو محسوب می شود. استفاده عاقلانه و فقط در مواقع ضروری مهم است.

ایجاد یک Singleton در پایتون

پایتون به طور بومی از الگوی Singleton پشتیبانی نمی کند، اما راه های مختلفی برای ایجاد آن وجود دارد. در اینجا یک مثال ساده آورده شده است:

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

در کد بالا، ما را باطل می کنیم __new__ روش. این روش قبلا نامیده می شود __init__ هنگامی که یک شی ایجاد می شود. اگر کلاس Singleton است _instance ویژگی است None، یک شی Singleton جدید ایجاد می کنیم و آن را به آن اختصاص می دهیم _instance. اگر _instance از قبل تنظیم شده است، در عوض آن را برمی گردانیم.

استفاده موثر از این تکنیک تنها اجازه می دهد Singleton کلاس یک بار نمونه سازی شود. سپس می توانید هر ویژگی یا روشی را که نیاز دارید به این کلاس اضافه کنید.

استفاده از دکوراتور

راه دیگر برای ایجاد یک Singleton در پایتون استفاده از دکوراتور است. دکوراتورها به ما اجازه می دهند تا عملکرد دیگری را بپیچانیم تا رفتار عملکرد پیچیده شده را گسترش دهیم، بدون اینکه به طور دائم آن را تغییر دهیم.

در اینجا روش ایجاد یک سینگلتون با استفاده از دکوراتور آمده است:

def singleton(cls):
    instances = {}
    def wrapper(*args, **kwargs):
        if cls not in instances:
            instances(cls) = cls(*args, **kwargs)
        return instances(cls)
    return wrapper

@singleton
class Singleton:
    pass

در کد بالا، @singleton دکوراتور بررسی می کند که آیا نمونه ای از کلاسی که تزئین می کند در آن وجود دارد یا خیر instances فرهنگ لغت. اگر این کار را نکرد، یکی را ایجاد می کند و به فرهنگ لغت اضافه می کند. اگر وجود داشته باشد، به سادگی نمونه موجود را برمی گرداند.

استفاده از کلاس پایه

ایجاد یک تک تون با استفاده از یک کلاس پایه یک رویکرد ساده است. در اینجا، ما یک کلاس پایه تعریف می کنیم که یک فرهنگ لغت از مراجع نمونه را حفظ می کند. هر زمان که یک نمونه درخواست می شود، ابتدا بررسی می کنیم که آیا نمونه از قبل در فرهنگ لغت وجود دارد یا خیر. اگر چنین شد، نمونه موجود را برمی گردانیم، در غیر این صورت، یک نمونه جدید ایجاد می کنیم و مرجع آن را در فرهنگ لغت ذخیره می کنیم.

در اینجا روش پیاده سازی singleton با استفاده از یک کلاس پایه در پایتون آمده است:

class SingletonBase:
    _instances = {}

    def __new__(cls, *args, **kwargs):
        if cls not in cls._instances:
            instance = super().__new__(cls)
            cls._instances(cls) = instance
        return cls._instances(cls)


class Singleton(SingletonBase):
    pass

s1 = Singleton()
s2 = Singleton()

print(s1 is s2)  

در کد بالا، SingletonBase کلاس پایه ای است که الگوی singleton را پیاده سازی می کند. Singleton کلاسی است که می خواهیم تک تن بسازیم.

یک متاکلاس در پایتون یک کلاس از یک کلاس است، به این معنی که یک کلاس نمونه ای از متاکلاس آن است. ما می توانیم از یک متاکلاس برای ایجاد یک سینگلتون با نادیده گرفتن آن استفاده کنیم __call__ روشی برای کنترل ایجاد نمونه ها

در اینجا روش پیاده سازی singleton با استفاده از متاکلاس در پایتون آمده است:

class SingletonMeta(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            instance = super().__call__(*args, **kwargs)
            cls._instances(cls) = instance
        return cls._instances(cls)


class Singleton(metaclass=SingletonMeta):
    pass


s1 = Singleton()
s2 = Singleton()

print(s1 is s2)  

در کد بالا، SingletonMeta متاکلاسی است که الگوی تک تن را اجرا می کند. Singleton کلاسی است که می خواهیم تک تن بسازیم.

موارد استفاده

Singleton ها زمانی مفید هستند که شما نیاز به کنترل دسترسی به یک منبع دارید یا زمانی که نیاز دارید نمونه سازی یک کلاس را به یک شی منفرد محدود کنید. این معمولاً در سناریوهایی مانند ورود به سیستم، اشیاء درایور، حافظه پنهان، استخرهای رشته و اتصالات پایگاه داده مفید است.

الگوی سینگلتون به دلیل ماهیت جهانی و پتانسیل عوارض جانبی ناخواسته، توسط برخی یک ضد الگو در نظر گرفته می شود. مطمئن شوید که فقط در مواقع ضروری از آن استفاده کنید!

Singletons و Multithreading

هنگام برخورد با چند نخی، تک‌تنه‌ها می‌توانند مشکل ساز باشند. اگر دو رشته همزمان بخواهند یک نمونه ایجاد کنند، ممکن است در نهایت دو نمونه متفاوت ایجاد کنند. برای جلوگیری از این امر، باید ایجاد نمونه را همگام سازی کنیم process.

در اینجا روش ایجاد تک‌تنه در یک محیط چند رشته‌ای آمده است:

import threading

class SingletonMeta(type):
    _instances = {}
    _lock: threading.Lock = threading.Lock()

    def __call__(cls, *args, **kwargs):
        with cls._lock:
            if cls not in cls._instances:
                instance = super().__call__(*args, **kwargs)
                cls._instances(cls) = instance
        return cls._instances(cls)


class Singleton(metaclass=SingletonMeta):
    pass


def test_singleton():
    s1 = Singleton()
    print(s1)



threads = (threading.Thread(target=test_singleton) for _ in range(10))


for thread in threads:
    thread.start()


for thread in threads:
    thread.join()

در کد بالا، ما از یک قفل استفاده می کنیم تا اطمینان حاصل کنیم که فقط یک رشته می تواند در هر زمان یک نمونه ایجاد کند. این امر از ایجاد نمونه های متعدد تکی در یک محیط چند رشته ای جلوگیری می کند.

دام های رایج

در حالی که تک‌تون‌ها می‌توانند ابزار قدرتمندی در جعبه ابزار برنامه‌نویسی پایتون شما باشند، اما بدون اشکال نیستند. در اینجا چند مورد رایج وجود دارد که باید به خاطر داشته باشید:

  1. متغیرهای جهانی: Singleton گاهی اوقات می تواند به عنوان یک متغیر جهانی مورد سوء استفاده قرار گیرد. این می تواند منجر به مشکلاتی شود زیرا وضعیت تک تنه می تواند توسط هر بخشی از کد تغییر کند و منجر به رفتار غیرقابل پیش بینی شود.

  2. آزمایش پذیری: Singletons می تواند تست واحد را دشوار کند. از آنجایی که آنها حالت بین تماس ها را حفظ می کنند، یک تست به طور بالقوه می تواند آن حالت را تغییر دهد و بر نتیجه آزمایش های دیگر تأثیر بگذارد. به همین دلیل مهم است که اطمینان حاصل شود که وضعیت قبل از هر آزمایش بازنشانی می شود.

  3. مسائل همزمانی: در یک محیط چند رشته ای، باید دقت شود که نمونه تکی تنها یک بار ایجاد شود. اگر به درستی مدیریت نشود، چندین رشته به طور بالقوه می توانند چندین نمونه ایجاد کنند.

در اینجا مثالی از این که چگونه تک قلو می تواند باعث مشکلات تست شود آورده شده است:

class Singleton(object):
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance

s1 = Singleton()
s2 = Singleton()

s1.x = 5
print(s2.x)  

در این مورد، اگر قرار بود رفتار شما را آزمایش کنید Singleton و اصلاح کنید x، این تغییر در همه موارد ادامه خواهد داشت و می تواند به طور بالقوه روی تست های دیگر تأثیر بگذارد.

نتیجه

Singletons یک الگوی طراحی است که یک کلاس را به یک نمونه محدود می کند. آنها می توانند در سناریوهایی که به یک منبع مشترک، مانند اتصال پایگاه داده یا فایل پیکربندی نیاز است، مفید باشند. در پایتون می‌توانید با استفاده از روش‌های مختلفی مانند دکوراتورها، کلاس‌های پایه و متاکلاس‌ها یک تک‌تون ایجاد کنید.

با این حال، تک‌نفره‌ها با مجموعه‌ای از دام‌ها همراه هستند، از جمله استفاده نادرست به‌عنوان متغیرهای سراسری، مشکلات در آزمایش، و مسائل همزمانی در محیط‌های چند رشته‌ای. آگاهی از این مسائل و استفاده عاقلانه از تک قلوها بسیار مهم است.

(برچسب‌ها به ترجمه)# python



منتشر شده در 1402-12-29 03:59:03

امتیاز شما به این مطلب
دیدگاه شما در خصوص مطلب چیست ؟

آدرس ایمیل شما منتشر نخواهد شد.

لطفا دیدگاه خود را با احترام به دیدگاه های دیگران و با توجه به محتوای مطلب درج کنید