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

سرور مجازی NVMe

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

0 11
زمان لازم برای مطالعه: 7 دقیقه


معرفی

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

پارادایم برنامه نویسی شی گرا (OOP).

الگوهای طراحی راه حل هایی برای مسائل رایج هستند که معمولاً وجود دارند، اما محدود به آن نیستند برنامه نویسی شی گرا (OOP) معماری ها OOP یکی از رایج ترین پارادایم های برنامه نویسی است، به دلیل ماهیت بصری آن و اینکه چقدر می تواند دنیای واقعی را منعکس کند. از طریق OOP، ما دنیای فیزیکی را به صورت نرم افزاری انتزاعی می کنیم و به ما امکان می دهد به طور طبیعی کد را مشاهده و بنویسیم. هر موجودیت تبدیل به یک می شود هدف – شی و این اشیاء می توانند با اشیاء دیگر مرتبط شوند – سلسله مراتبی از اشیاء را در یک سیستم تشکیل می دهند.

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

کتابخانه ABC

پارادایم OOP معمولاً از استفاده از کلاس های انتزاعی، که یک ویژگی داخلی در پایتون نیستند. برای دستیابی به این قابلیت، ما از کتابخانه ABC (کلاس های پایه چکیده)..

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

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

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

سه دسته اصلی الگوی طراحی وجود دارد:

  • الگوهای طراحی خلاقانه – با ایجاد امکان ایجاد اشیا در حالی که منطق ایجاد شیء را انتزاع یا پنهان می کند.
  • الگوهای طراحی سازه – در نظر گرفته شده برای رسیدگی به ترکیب اشیاء و کلاس ها، با تکیه روی وراثت برای کنترل چگونگی ساختار اشیاء.
  • الگوهای طراحی رفتاری – متمرکز روی ارتباطی که بین اشیا اتفاق می افتد، کنترل روش حرکت داده ها بین اشیا، و توزیع رفتار بین کلاس ها.

شهود الگوی اولیه

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

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

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

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

  • نمونه اولیه: Superclass شامل تمام ویژگی ها و روش های واجب پایه ای خواهد بود که کلون ها هنگام کپی کردن آن دارند Prototype کلاس همچنین، نمونه اولیه دارای یک چکیده است clone() روش ، که باید توسط همه زیر کلاس ها اجرا شود.
  • کلاس(های) بتن: هنگامی که ما ایجاد کردیم Prototype، ما می توانیم کلاس های بتونی را مبتنی بر خود شروع کنیم روی آی تی. کلاس های بتونی می توانند ویژگی ها و روش های خاص خود را داشته باشند ولی آنها همیشه ویژگی های نمونه اولیه اصلی و نسخه رونویسی شده از آن را خواهند داشت clone().

نمونه اولیه تصویر الگوی طراحی

اجرای نمونه اولیه الگو در پایتون

ما چند نوع NPC برای یک بازی ویدیویی تخیلی ایجاد خواهیم کرد – a Shopkeeper، آ Warrior و الف Mage.

هر یک از آنها یک NPC، یک سوپرکلاس مشترک هستند – اما آنها ویژگی های متفاوتی خواهند داشت. این Shopkeeper دارد charisma، بنابراین آنها می توانند بهتر مبادله کنند، در حالی که Mage دارد mana بجای stamina، مانند Warrior میکند.

ما Prototype class به معنای NPC های عمومی است و از آن می توانیم کلاس های بتن خود را پیاده سازی کنیم. تاخیر خواهیم داشت هر دو را Prototype سازنده و خود کلاس های بتنی، به تمسخر یک فراخوان گران قیمت در سازنده – تاخیر در اجرای کد چند ثانیه، ایجاد هر شی جدید را به یک عملیات بسیار گران تبدیل می کند.

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

تعریف کلاس نمونه اولیه

بیایید با سوپرکلاس شروع کنیم Prototype برای NPC ها آن clone() متد خالی خواهد بود، اما زیر کلاس های آن آن را پیاده سازی می کنند. به طور طبیعی، شامل تمام ویژگی های پایه برای زیر کلاس ها نیز می شود. از آنجایی که می‌خواهیم همه زیر کلاس‌ها لزوماً این را پیاده‌سازی کنند clone() روش، به عنوان علامت گذاری شده است @abstractmethod. حاشیه نویسی از کتابخانه ABC و روش های انتزاعی پیاده سازی را ارائه نمی دهند، اما باید توسط زیر کلاس ها پیاده سازی شود:

from abc import ABC, abstractmethod
import time


class Prototype(ABC):
    
    def __init__(self):
        
        time.sleep(3)
        
        self.height = None
        self.age = None
        self.defense = None
        self.attack = None

    
    @abstractmethod
    def clone(self):
        pass  

کلاس های بتن

حالا بیایید کلاس های بتن خود را بر اساس تعریف کنیم روی را Prototype. ما نادیده گرفته خواهیم شد clone() روش و در واقع پیاده سازی برای آن فراهم می کند. برای کپی کردن اشیاء، از آن استفاده خواهیم کرد copy کتابخانه ای که در پایتون تعبیه شده است. این copy() روش کتابخانه یک کپی کم عمق از یک شی، در حالی که a deepcopy() الف را ایجاد می کند کپی عمیق از یک شی بسته به روی ساختار اشیاء شما – شما یکی یا دیگری را ترجیح می دهید.

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

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

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

from prototype import Prototype
import copy
import time

class Shopkeeper(Prototype):
    def __init__(self, height, age, defense, attack):
        super().__init__()
        
        time.sleep(3)
        self.height = height
        self.age = age
        self.defense = defense
        self.attack = attack
        
        self.charisma = 30

    
    def clone(self):
        return copy.deepcopy(self)    

این Warrior NPC مجموعه دیگری از مقادیر پایه دارد:

from prototype import Prototype
import copy
import time

class Warrior(Prototype):
    def __init__(self, height, age, defense, attack):
        
        
        self.stamina = 60
    
    def clone(self):
        return copy.deepcopy(self)  

و در نهایت، Mage:

from prototype import Prototype
import copy
import time

class Mage(Prototype):
     def __init__(self, height, age, defense, attack):
     
     self.mana = 100

    
    def clone(self):
        return copy.deepcopy(self) 

آزمایش الگوی طراحی نمونه اولیه در پایتون

اکنون می‌توانیم الگو را آزمایش کنیم. ابتدا یک نمونه از a ایجاد می کنیم Shopkeeper همانطور که هست، زمان لازم را یادداشت کنید:

print('Starting to create a Shopkeeper NPC: ', datetime.datetime.now().time())
shopkeeper = Shopkeeper(180, 22, 5, 8)
print('Finished creating a Shopkeeper NPC: ', datetime.datetime.now().time())
print('Attributes: ' + ', '.join("%s: %s" % item for item in vars(shopkeeper).items()))

این منجر به 6 ثانیه انتظار – 3 از طرف می شود Prototype و 3 از Shopkeeper، اما در نهایت شیء را 6 ثانیه بعد ایجاد می کند:

Starting to create a Shopkeeper NPC:  15:57:40.852336
Finished creating a Shopkeeper NPC:  15:57:46.859203
Attributes: height: 180, age: 22, defense: 5, attack: 8, charisma: 30

همانطور که انتظار می رفت، این یک عمل دردناک آهسته است. اگر به مغازه دار دیگری نیاز داشته باشیم چه اتفاقی می افتد؟ یا بهتر از آن – اگر به 5 مغازه دار دیگر نیاز داشته باشیم چه؟ بیایید صنفی را مثال بزنیم که شامل 5 مغازه دار است:

print('Instantiating trader guild at: ', datetime.datetime.now().time())
for i in range(5):
    shopkeeper = Shopkeeper(180, 22, 5, 8)
    print(f'Finished creating a Shopkeeper NPC {i} at: ', datetime.datetime.now().time())
print('Finished instantiating trader guild at: ', datetime.datetime.now().time())
Instantiating trader guild at:  16:15:14.353285
Finished creating a Shopkeeper NPC 0 at:  16:15:20.360971
Finished creating a Shopkeeper NPC 1 at:  16:15:26.365997
Finished creating a Shopkeeper NPC 2 at:  16:15:32.370327
Finished creating a Shopkeeper NPC 3 at:  16:15:38.378361
Finished creating a Shopkeeper NPC 4 at:  16:15:44.383375
Finished instantiating trader guild at:  16:15:44.383674

در عوض، ما می توانیم شبیه را اولین مغازه دار، با توجه به این واقعیت که همه آنها از یک الگو پیروی می کنند و می توانند جایگزین شوند:

print('Instantiating trader guild at: ', datetime.datetime.now().time())
shopkeeper_template = Shopkeeper(180, 22, 5, 8)
for i in range(5):
    shopkeeper_clone = shopkeeper_template.clone()
    print(f'Finished creating a Shopkeeper clone {i} at: ', datetime.datetime.now().time())
print('Finished instantiating trader guild at: ', datetime.datetime.now().time())

که منجر به:

Instantiating trader guild at:  16:19:24.965780
Finished creating a Shopkeeper clone 0 at:  16:19:30.975445
Finished creating a Shopkeeper clone 1 at:  16:19:30.975763
Finished creating a Shopkeeper clone 2 at:  16:19:30.975911
Finished creating a Shopkeeper clone 3 at:  16:19:30.976058
Finished creating a Shopkeeper clone 4 at:  16:19:30.976132
Finished instantiating trader guild at:  16:19:30.976529

اکنون، تنها چیزی که لازم است اولین قالب است Shopkeeper نمونه سازی شود، و ما می توانیم آن را شبیه سازی کنیم نانوثانیه. کل 5 کلون فقط گرفت 0.001 ثانیه برای اجرا

اکنون، ما می توانیم یک جمعیت کامل از NPC های مختلف بدون مشکل ایجاد کنیم:

print('Instantiating 1000 NPCs: ', datetime.datetime.now().time())
shopkeeper_template = Shopkeeper(180, 22, 5, 8)
warrior_template = Warrior(185, 22, 4, 21)
mage_template = Mage(172, 65, 8, 15)
for i in range(333):
    shopkeeper_clone = shopkeeper_template.clone()
    warrior_clone = warrior_template.clone()
    mage_clone = mage_template.clone()
    print(f'Finished creating NPC trio clone {i} at: ', datetime.datetime.now().time())
print('Finished instantiating NPC population at: ', datetime.datetime.now().time())

که منجر به 1000 نسخه می شود که در کل کپی کردن همه آنها 0.1 ثانیه طول کشید:

Instantiating 1000 NPCs:  16:27:14.566635
Finished creating NPC trio clone 0 at:  16:27:32.591992
...
Finished creating NPC trrio clone 331 at:  16:27:32.625681
Finished creating NPC trio clone 332 at:  16:27:32.625764
Finished instantiating NPC population at:  16:27:32.625794

نتیجه

ایجاد اشیاء پیچیده، به خصوص اگر به تماس های پایگاه داده گران قیمت نیاز داشته باشند، زمان بر است.

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

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



منتشر شده در 1403-01-09 15:45:06

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

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

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