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

سرور مجازی NVMe

الگوهای طراحی خلاقانه در پایتون

0 4
زمان لازم برای مطالعه: 12 دقیقه


معرفی

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

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

الگوهای طراحی پوشش داده شده در این بخش عبارتند از:

الگوی طراحی کارخانه

فرض کنید در حال ساختن نرم افزاری برای یک شرکت بیمه هستید که به افرادی که به صورت تمام وقت مشغول به کار هستند، بیمه ارائه می دهد. شما برنامه را با استفاده از کلاسی به نام ساخته اید Worker.

با این حال، مشتری تصمیم به گسترش کسب و کار خود گرفت و اکنون خدمات خود را به افراد بیکار نیز ارائه خواهد کرد، اما با رویه ها و شرایط متفاوت.

اکنون باید یک کلاس کاملاً جدید برای افراد بیکار بسازید که سازنده کاملاً متفاوتی می گیرد! اما اکنون نمی دانید کدام سازنده را در یک حالت کلی فراخوانی کنید، چه رسد به اینکه کدام آرگومان ها را به آن منتقل کنید.

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

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

بدون تاکید بر این موضوع، به خوبی می‌دانید که این رویکرد چندان مطلوب، غیر مقیاس‌پذیر و در کل ناپایدار است.

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

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

با استفاده از یک کارخانه، می‌توانیم یک پیاده‌سازی را با تغییر پارامتری که در ابتدا برای تصمیم‌گیری در مورد پیاده‌سازی اصلی استفاده شده بود، با دیگری تغییر دهیم.

این پیاده‌سازی را از کاربرد جدا می‌کند به‌گونه‌ای که می‌توانیم به راحتی برنامه را با افزودن پیاده‌سازی‌های جدید و نمونه‌سازی آنها از طریق کارخانه – دقیقاً با همان پایگاه کد، مقیاس‌بندی کنیم.

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

برای شروع، استفاده از روش های انتزاعی را فراموش نکنید:

from abc import ABC, abstractmethod

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

class Product(ABC):

    @abstractmethod
    def calculate_risk(self):
        pass

و اکنون از طریق الف از آن به ارث می بریم Worker و Unemployed:

class Worker(Product):
    def __init__(self, name, age, hours):
        self.name = name
        self.age = age
        self.hours = hours

    def calculate_risk(self):
        
        return self.age + 100/self.hours

    def __str__(self):
        return self.name+" ("+str(self.age)+") - "+str(self.hours)+"h/week"


class Unemployed(Product):
    def __init__(self, name, age, able):
        self.name = name
        self.age = age
        self.able = able

    def calculate_risk(self):
        
        if self.able:
            return self.age+10
        else:
            return self.age+30

    def __str__(self):
        if self.able:
            return self.name+" ("+str(self.age)+") - able to work"
        else:
            return self.name+" ("+str(self.age)+") - unable to work"

اکنون که افراد خود را داریم، بیایید کارخانه آنها را بسازیم:

class PersonFactory:
    def get_person(self, type_of_person):
        if type_of_person == "worker":
            return Worker("Oliver", 22, 30)
        if type_of_person == "unemployed":
            return Unemployed("Sophie", 33, False)

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

برای آزمایش روش عملکرد همه اینها، بیایید کارخانه خود را نمونه سازی کنیم و اجازه دهیم چند نفر تولید کند:

factory = PersonFactory()

product = factory.get_person("worker")
print(product)

product2 = factory.get_person("unemployed")
print(product2)

این به شما می دهد:

Oliver (22) - 30h/week
Sophie (33) - unable to work

الگوی طراحی کارخانه انتزاعی

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

به عنوان مثال، ممکن است لازم باشد یک غذای اصلی و یک دسر در یک رستوران ایتالیایی و یک رستوران فرانسوی درست کنید، اما یک غذا را با دیگری مخلوط نمی کنید.

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

یک کارخانه انتزاعی مسئول ایجاد گروه های کامل از اشیاء، در کنار کارخانه های مربوطه خود است – اما خود را به اجرای عینی این اشیاء نمی پردازد. آن قسمت برای کارخانه های مربوطه خود باقی مانده است:

from abc import ABC, abstractmethod

class Product(ABC):

    @abstractmethod
    def cook(self):
        pass

class FettuccineAlfredo(Product):
    name = "Fettuccine Alfredo"
    def cook(self):
        print("Italian main course prepared: "+self.name)

class Tiramisu(Product):
    name = "Tiramisu"
    def cook(self):
        print("Italian dessert prepared: "+self.name)

class DuckALOrange(Product):
    name = "Duck À L'Orange"
    def cook(self):
        print("French main course prepared: "+self.name)

class CremeBrulee(Product):
    name = "Crème brûlée"
    def cook(self):
        print("French dessert prepared: "+self.name)

class Factory(ABC):

    @abstractmethod
    def get_dish(type_of_meal):
        pass

class ItalianDishesFactory(Factory):
    def get_dish(type_of_meal):
        if type_of_meal == "main":
            return FettuccineAlfredo()
        if type_of_meal == "dessert":
            return Tiramisu()

    def create_dessert(self):
        return Tiramisu()

class FrenchDishesFactory(Factory):
    def get_dish(type_of_meal):
        if type_of_meal == "main":
            return DuckALOrange()

        if type_of_meal == "dessert":
            return CremeBrulee()

class FactoryProducer:
    def get_factory(self, type_of_factory):
        if type_of_factory == "italian":
            return ItalianDishesFactory
        if type_of_factory == "french":
            return FrenchDishesFactory

ما می توانیم نتایج را با ایجاد هر دو کارخانه و فراخوانی مربوطه آزمایش کنیم cook() مواد و روش ها روی همه اشیا:

fp = FactoryProducer()

fac = fp.get_factory("italian")
main = fac.get_dish("main")
main.cook()
dessert = fac.get_dish("dessert")
dessert.cook()

fac1 = fp.get_factory("french")
main = fac1.get_dish("main")
main.cook()
dessert = fac1.get_dish("dessert")
dessert.cook()

این کد ابتدا غذای اصلی و دسر ایتالیایی و بعد از آن غذای فرانسوی را آماده می کند:

Italian main course prepared: Fettuccine Alfredo
Italian dessert prepared: Tiramisu
French main course prepared: Duck À L'Orange
French dessert prepared: Crème brûlée

الگوی طراحی سازنده

فرض کنید باید یک ربات را با ساختار جسم خود نشان دهید. این ربات می تواند انسان نما با چهار دست و پا و ایستاده به سمت بالا باشد یا می تواند شبیه حیوانات با دم، بال و … باشد و از چرخ برای حرکت استفاده کند یا از تیغه های هلیکوپتر استفاده کند. می تواند از دوربین ها، یک ماژول تشخیص مادون قرمز و غیره استفاده کند روی. شما عکس را دریافت می کنید.

سازنده این مورد را تصور کنید:

def __init__(self, left_leg, right_leg, left_arm, right_arm,
             left_wing, right_wing, tail, blades, cameras,
             infrared_module, 
             ):
    self.left_leg = left_leg
    if left_leg == None:
        bipedal = False
    self.right_leg = right_leg
    self.left_arm = left_arm
    self.right_arm = right_arm
    

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

همچنین، اگر نخواهیم ربات پیاده سازی کند، چه می شود همه زمینه های داخل کلاس؟ چه می شود اگر بخواهیم به جای داشتن هر دو پا فقط پا داشته باشد و چرخ ها؟

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

برای غلبه بر این، ما می توانیم یک سازنده کلاسی که شی ما را می سازد و ماژول های مناسب را به ربات ما اضافه می کند. به جای یک سازنده پیچیده، می‌توانیم یک شی را نمونه‌سازی کنیم و اجزای مورد نیاز را با استفاده از توابع اضافه کنیم.

ما ساخت هر ماژول را به طور جداگانه پس از نمونه سازی شیء فراخوانی می کنیم. بیایید جلو برویم و a را تعریف کنیم Robot با چند مقدار پیش فرض:

class Robot:
    def __init__(self):
        self.bipedal = False
        self.quadripedal = False
        self.wheeled = False
        self.flying = False
        self.traversal = ()
        self.detection_systems = ()

    def __str__(self):
        string = ""
        if self.bipedal:
            string += "BIPEDAL "
        if self.quadripedal:
            string += "QUADRIPEDAL "
        if self.flying:
            string += "FLYING ROBOT "
        if self.wheeled:
            string += "ROBOT روی WHEELS\n"
        else:
            string += "ROBOT\n"

        if self.traversal:
            string += "Traversal modules installed:\n"

        for module in self.traversal:
            string += "- " + str(module) + "\n"

        if self.detection_systems:
            string += "Detection systems installed:\n"

        for system in self.detection_systems:
            string += "- " + str(system) + "\n"

        return string

class BipedalLegs:
    def __str__(self):
        return "two legs"

class QuadripedalLegs:
    def __str__(self):
        return "four legs"

class Arms:
    def __str__(self):
        return "four legs"

class Wings:
    def __str__(self):
        return "wings"

class Blades:
    def __str__(self):
        return "blades"

class FourWheels:
    def __str__(self):
        return "four wheels"

class TwoWheels:
    def __str__(self):
        return "two wheels"

class CameraDetectionSystem:
    def __str__(self):
        return "cameras"

class InfraredDetectionSystem:
    def __str__(self):
        return "infrared"

توجه داشته باشید که ما مقداردهی اولیه را در سازنده حذف کرده ایم و به جای آن از مقادیر پیش فرض استفاده کرده ایم. این به این دلیل است که ما از آن استفاده خواهیم کرد سازنده کلاس هایی برای مقداردهی اولیه این مقادیر.

ابتدا یک چکیده را پیاده سازی می کنیم سازنده که رابط ما را برای ساختن تعریف می کند:

from abc import ABC, abstractmethod

class RobotBuilder(ABC):

    @abstractmethod
    def reset(self):
        pass

    @abstractmethod
    def build_traversal(self):
        pass

    @abstractmethod
    def build_detection_system(self):
        pass

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

class AndroidBuilder(RobotBuilder):
    def __init__(self):
        self.product = Robot()

    def reset(self):
        self.product = Robot()

    def get_product(self):
        return self.product

    def build_traversal(self):
        self.product.bipedal = True
        self.product.traversal.append(BipedalLegs())
        self.product.traversal.append(Arms())

    def build_detection_system(self):
        self.product.detection_systems.append(CameraDetectionSystem())

class AutonomousCarBuilder(RobotBuilder):
    def __init__(self):
        self.product = Robot()

    def reset(self):
        self.product = Robot()

    def get_product(self):
        return self.product

    def build_traversal(self):
        self.product.wheeled = True
        self.product.traversal.append(FourWheels())

    def build_detection_system(self):
        self.product.detection_systems.append(InfraredDetectionSystem())

توجه کنید که چگونه روش‌های مشابهی را پیاده‌سازی می‌کنند، اما ساختار ذاتاً متفاوتی از اشیاء در زیر وجود دارد، و کاربر نهایی نیازی به پرداختن به جزئیات آن ساختار ندارد؟

البته، ما می توانیم یک Robot که می تواند هر دو پایه و چرخ داشته باشد و کاربر باید هر کدام را جداگانه اضافه کند، اما ما همچنین می توانیم سازنده های بسیار خاصی بسازیم که فقط یک ماژول مناسب برای هر “قسمت” اضافه می کنند. بیایید استفاده از یک را امتحان کنیم AndroidBuilder برای ساخت اندروید:

builder = AndroidBuilder()
builder.build_traversal()
builder.build_detection_system()
print(builder.get_product())

با اجرای این کد به دست می آید:

BIPEDAL ROBOT
Traversal modules installed:
- two legs
- four legs
Detection systems installed:
- cameras

و حالا بیایید از an استفاده کنیم AutonomousCarBuilder برای ساخت ماشین:

builder = AutonomousCarBuilder()
builder.build_traversal()
builder.build_detection_system()
print(builder.get_product())

با اجرای این کد به دست می آید:

ROBOT روی WHEELS
Traversal modules installed:
- four wheels
Detection systems installed:
- infrared

مقداردهی اولیه در مقایسه با سازنده آشفته قبلی بسیار تمیزتر و خواناتر است و ما انعطاف پذیری اضافه کردن ماژول ها را داریم. ما میخواهیم.

اگر در زمینه های محصول ما از سازنده های نسبتا استاندارد استفاده کنیم، حتی می توانیم به اصطلاح بسازیم کارگردان برای مدیریت سازندگان خاص:

class Director:
    def make_android(self, builder):
        builder.build_traversal()
        builder.build_detection_system()
        return builder.get_product()

    def make_autonomous_car(self, builder):
        builder.build_traversal()
        builder.build_detection_system()
        return builder.get_product()

director = Director()
builder = AndroidBuilder()
print(director.make_android(builder))

با اجرای این قطعه کد به دست می آید:

BIPEDAL ROBOT
Traversal modules installed:
- two legs
- four legs
Detection systems installed:
- cameras

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

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

الگوی طراحی اولیه

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

اگر بخواهیم مستقیماً این کار را انجام دهیم، وابستگی‌های زیادی را به کد خود اضافه می‌کنیم، و حتی ممکن است در پایان کار نکند.

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

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

from abc import ABC, abstractmethod

class Prototype(ABC):
    def clone(self):
        pass

class MyObject(Prototype):
    def __init__(self, arg1, arg2):
        self.field1 = arg1
        self.field2 = arg2

    def __operation__(self):
        self.performed_operation = True

    def clone(self):
        obj = MyObject(self.field1, field2)
        obj.performed_operation = self.performed_operation
        return obj

به طور متناوب، می توانید از deepcopy تابع به جای اختصاص دادن فیلدهای ساده مانند مثال قبلی:

class MyObject(Prototype):
    def __init__(self, arg1, arg2):
        self.field1 = arg1
        self.field2 = arg2

    def __operation__(self):
        self.performed_operation = True

    def clone(self):
        return deepcopy(self)

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

الگوی طراحی Singleton

آ سینگلتون یک شی با دو ویژگی اصلی است:

  • حداکثر می تواند یک نمونه داشته باشد
  • باید به صورت جهانی در برنامه قابل دسترسی باشد

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

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

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

بیایید جلو برویم و اجرا کنیم سینگلتون الگو با ایجاد یک شی در سطح جهانی و محدود به یک نمونه واحد:

from typing import Optional

class MetaSingleton(type):
    _instance : Optional(type) = None
    def __call__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super(MetaSingleton, cls).__call__(*args, **kwargs)
        return cls._instance

class BaseClass:
    field = 5

class Singleton(BaseClass, metaclass=MetaSingleton):
    pass

Optional در اینجا یک نوع داده وجود دارد که می تواند شامل هر یک از کلاس های ذکر شده در آن باشد () یا None.

تعریف الف __call__() متد به شما امکان می دهد از نمونه های کلاس به عنوان توابع استفاده کنید. این متد در هنگام مقداردهی اولیه نیز فراخوانی می شود، بنابراین وقتی چیزی شبیه به آن را فراخوانی می کنیم a = Singleton() زیر کاپوت آن را کلاس پایه خود می نامد __call__() روش.

در پایتون همه چیز یک شی است. که شامل کلاس ها می شود. تمام کلاس های معمولی که می نویسید، و همچنین کلاس های استاندارد، دارند type به عنوان نوع شی آنها. زوج type از نوع است type. این به این معنی است که type یک متاکلاس است – کلاس های دیگر نمونه هایی از آن هستند typeدرست مانند اشیاء متغیر نمونه هایی از آن کلاس ها هستند. در مورد ما، Singleton نمونه ای از MetaSingleton.

همه اینها به این معنی است که ما __call__() هر زمان که یک شی جدید ایجاد شود، متد فراخوانی می شود و اگر قبلاً آن را مقداردهی نکرده باشیم، نمونه جدیدی را ارائه می دهد. اگر داشته باشیم، فقط نمونه اولیه اولیه را برمی گرداند.

super(MetaSingleton, cls).__call__(*args, **kwargs) سوپرکلاس را می خواند __call__. سوپرکلاس ما در این مورد است type، که دارای یک __call__ پیاده سازی که مقداردهی اولیه را با آرگومان های داده شده انجام می دهد.

ما نوع خود را مشخص کرده ایم (MetaSingleton، مقداری که باید به آن نسبت داده شود _instance رشته (cls) و استدلال های دیگری که ممکن است از آنها عبور کنیم.

هدف از استفاده از متاکلاس در این مورد به جای اجرای ساده تر، اساساً توانایی استفاده مجدد از کد است.

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

اکنون می توانیم استفاده از آن را امتحان کنیم:

a = Singleton()
b = Singleton()

a == b
True

به دلیل نقطه دسترسی جهانی آن، عاقلانه است که ایمنی نخ را در آن ادغام کنید سینگلتون. خوشبختانه، برای انجام این کار نیازی به ویرایش زیاد آن نداریم. ما به سادگی می توانیم ویرایش کنیم MetaSingleton اندکی:

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

به این ترتیب، اگر دو رشته شروع به نمونه سازی کنند سینگلتون در همان زمان، یکی در قفل متوقف خواهد شد. هنگامی که مدیر زمینه قفل را آزاد می کند، دیگری وارد قفل می شود if عبارت و ببینید که نمونه در واقع قبلاً توسط رشته دیگر ایجاد شده است.

الگوی طراحی استخر آبجکت

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

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

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

بیایید جلو برویم و ابتدا تعریف کنیم MyClass:

class MyClass:
    
    def reset(self):
        self.setting = 0

class ObjectPool:

    def __init__(self, size):
        self.objects = (MyClass() for _ in range(size))

    def acquire(self):
        if self.objects:
            return self.objects.pop()
        else:
            self.objects.append(MyClass())
            return self.objects.pop()

    def release(self, reusable):
        reusable.reset()
        self.objects.append(reusable)

و برای آزمایش آن:

pool = ObjectPool(10)
reusable = pool.acquire()
pool.release(reusable)

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

تخصیص اشیایی که فقط حافظه را اشغال می کنند (به این معنی که هیچ منبع خارجی ندارند) در چنین زبان هایی نسبتاً ارزان است، در حالی که بسیاری از ارجاعات “زنده” به اشیاء می توانند جمع آوری زباله را کاهش دهند زیرا از همه مراجع عبور می کند.

نتیجه

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

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



منتشر شده در 1403-01-19 00:22:04

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

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

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