از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
الگوی طراحی آداپتور در پایتون
سرفصلهای مطلب
معرفی
این الگوی طراحی آداپتور محبوب است الگوی طراحی سازه مورد استفاده در مهندسی نرم افزار این راهنما به چگونگی پیاده سازی الگوی طراحی آداپتور در پایتون می پردازد.
الگوهای طراحی راه حل هایی شبیه به الگو هستند – عملا دستور العمل هایی برای حل مشکلات تکراری و رایج در توسعه نرم افزار. الگوی آداپتور بر اساس مفهوم آداپتور دنیای واقعی است! به عنوان مثال، شارژر لپ تاپ ممکن است یک دوشاخه 3 پین در انتهای آن داشته باشد، اما پریز دیواری ممکن است فقط یک سوکت 2 پین باشد. برای وصل کردن یک شارژر 3 پین به این پریز، به یک آداپتور نیاز داریم که یک دوشاخه 3 پین را بپذیرد، و سازگار می کند رابط به 2 پین سوکت
یک شارژر 2 پین و یک شارژر 3 پین دارند همان عملکرد اصلی (الکتریسیته را از سوکت به لپ تاپ منتقل کنید)، اما داشته باشید یک فرم متفاوت، و شخص به راحتی می تواند سازگار شدن به دیگری هر زمان که اجزای نرم افزاری با عملکرد اصلی یکسان اما اشکال متفاوت دارید، می توانید الگوی طراحی آداپتور را اعمال کنید.
الگوی آداپتور دقیقاً از این اصل پیروی می کند. این اجازه می دهد تا دو اینترفیس ناسازگار با یکدیگر بدون تغییر اجزای داخلی هر جزء کار کنند. این با تطبیق یک رابط، به دیگری، به صورت خارجی به دست می آید.
بیایید قبل از غواصی عمیق تر به دنیای الگوهای آداپتور، به برخی اصطلاحات اساسی نگاه کنیم:
- رابط مشتری: رابطی که توابعی را که کلاینت باید پیاده سازی کند را مشخص می کند.
- مشتری: کلاسی که رابط مشتری را پیاده سازی می کند.
- سازگار/خدمات: کلاس ناسازگاری که نیاز به همکاری با رابط مشتری دارد.
- آداپتور: کلاسی که همکاری بین سرویس و مشتری را ممکن می کند.
انواع مختلف الگوهای آداپتور
الگوی طراحی آداپتور را می توان به دو روش مختلف پیاده سازی کرد:
آداپتور شی
با این روش، کلاس آداپتور متدها را از رابط مشتری پیاده سازی می کند. بنابراین، شی مشتری و شی آداپتور با یکدیگر سازگار هستند. شیء سرویس a را تشکیل می دهد has-a
رابطه با شی آداپتور یعنی شیء سرویس متعلق به شی آداپتور است.
ما می دانیم که کلاس خدمات با مشتری سازگار نیست. کلاس آداپتور با نمونه سازی خود با آن شی، در اطراف شیء سرویس می پیچد. اکنون، شیء سرویس از طریق شیء آداپتور قابل دسترسی است و به مشتری امکان می دهد با آن تعامل داشته باشد.
ما می توانیم شی آداپتور را در تمام زبان های برنامه نویسی مدرن پیاده سازی کنیم.
آداپتور کلاس
با این روش، آداپتور دارای یک is-a
ارتباط با کلاس خدمات در این سناریو، آداپتور متدهای مورد نیاز مشتری را پیادهسازی میکند، اما از چندین سازگار به ارث میبرد و به آن توانایی فراخوانی مستقیم توابع ناسازگار آنها را میدهد. بزرگترین اشکال این تنوع این است که ما فقط می توانیم از آن در زبان های برنامه نویسی استفاده کنیم که از وراثت چندگانه کلاس ها پشتیبانی می کنند.
پیاده سازی الگوی طراحی آداپتور در پایتون
در بخش زیر، الگوی طراحی آداپتور را در پایتون پیاده سازی می کنیم، به طور خاص با استفاده از تنوع آداپتور شی. بخش به دو بخش تقسیم می شود. ابتدا محیطی را ایجاد می کنیم که از الگوی آداپتور استفاده شود. مهم است که به وضوح ببینید این الگو چگونه می تواند برخی از مشکلات نرم افزاری را حل کند. بخش دوم از یک آداپتور برای حل مشکل استفاده می کند.
مشکل ناسازگاری بین کلاس ها
بیایید به مسئله سازگاری زمانی که کلاس سرویس گیرنده و سرویس عملکردهای مختلف را پیاده سازی می کنند، نگاه کنیم. یک کلاس کلاینت با روش های زیر ایجاد کنید و آن را در یک پوشه به عنوان ذخیره کنید car.py
:
import random
class Car:
def __init__(self):
self.generator = random.Random()
def accelerate(self):
random_num = self.generator.randint(50, 100)
speed = random_num
print(f"The speed of the car is {speed} mph")
def apply_brakes(self):
random_num = self.generator.randint(20, 40)
speed = random_num
print(f"The speed of the car is {speed} mph after applying the brakes")
def assign_driver(self, driver_name):
print(f"{driver_name} is driving the car")
در اینجا، ما ایجاد کرده ایم Car
کلاس با سه روش: accelerate()
، apply_brakes()
و assign_driver()
. ما وارد کردیم random
ماژول و از آن برای تولید اعدادی استفاده کرد که پس از شتاب گیری و ترمز کردن، سرعت خودرو را تعیین می کند. این assign_driver()
متد نام راننده ماشین را نشان می دهد.
در مرحله بعد، ما باید یک کلاس سرویس یا سازگار ایجاد کنیم که مایل به همکاری با کلاس مشتری است Car
. یک کلاس موتور سیکلت مانند این ایجاد کنید و آن را در پوشه خود ذخیره کنید motorcycle.py
:
import random
class Motorcycle:
def __init__(self):
self.generator = random.Random()
def rev_throttle(self):
random_num = self.generator.randint(50, 100)
speed = random_num
print(f"The speed of the motorcycle is {speed} mph")
def pull_brake_lever(self):
random_num = self.generator.randint(20, 40)
speed = random_num
print(
f"The speed of the motorcycle is {speed} mph after applying the brakes")
def assign_rider(self, rider_name):
print(f"{rider_name} is riding the motorcycle")
یک کلاس خدماتی، Motorcycle
در بالا با سه روش ایجاد شده است rev_throttle()
، pull_brake_lever()
، و assign_rider()
. به تفاوت بین متدهای کلاس سرویس و کلاینت با وجود عملکرد مشابه آنها توجه کنید. این accelerator()
روش افزایش سرعت خودرو در حالی که rev_throttle()
روشی که باعث افزایش سرعت موتور سیکلت می شود. به همین ترتیب، apply_brakes()
و pull_brake_lever()
در وسایل نقلیه مربوطه ترمز بگیرید. در نهایت، assign_driver()
و assign_rider()
روش ها اپراتور خودرو را تعیین می کند.
در مرحله بعد، بیایید یک کلاس برای دسترسی به این متدهای مختلف ایجاد کنیم. ابتدا یک عدد را اضافه کنید __init.py__
در همان پوشه ای که ایجاد کردید car.py
و motorcycle.py
:
touch __init__.py
حالا کد زیر را در یک فایل جدید اضافه کنید drive.py
:
from car import Car
from motorcycle import Motorcycle
import traceback
if __name__ == '__main__':
car = Car()
bike = Motorcycle()
print("The Motorcycle\n")
bike.assign_rider("Subodh")
bike.rev_throttle()
bike.pull_brake_lever()
print("\n")
print("The Car\n")
car.assign_driver("Sushant")
car.accelerate()
car.apply_brakes()
print("\n")
print("Attempting to call client methods with the service object\n")
try:
bike.assign_driver("Robert")
bike.accelerate()
bike.apply_brakes()
except AttributeError:
print("Oops! bike object cannot access car methods")
traceback.print_exc()
این اسکریپت اشیاء مشتری و سرویس ما را ایجاد می کند. ما اول import را Car
و Motorcycle
کلاس ها و ایجاد اشیاء با آنها. سپس متدها را از the فراخوانی می کنیم bike
هدف – شی (Motorcycle
کلاس). پس از آن، ما متدهای را فراخوانی می کنیم car
هدف – شی (Car
کلاس). وقتی اجرا شد، تمام کدهایی که تا به حال ذکر شد کار خواهند کرد.
با این حال، زمانی که ما سعی می کنیم از روش های the استفاده کنیم، یک استثنا مطرح می شود Car
کلاس با bike
هدف – شی. وقتی این اسکریپت را اجرا می کنیم:
The Motorcycle
Subodh is riding the motorcycle
The speed of the motorcycle is 91 mph
The speed of the motorcycle is 37 mph after applying the brakes
The Car
Sushant is driving the car
The speed of the car is 59 mph
The speed of the car is 33 mph after applying the brakes
Attempting to call client methods with the service object
Oops! bike object cannot access car methods
Traceback (most recent call last):
File "drive.py", line 24, in <module>
bike.assign_driver("Robert")
AttributeError: 'Motorcycle' object has no attribute 'assign_driver'
در این صورت میتوانیم آن را اصلاح کنیم Motorcycle
کلاس یا drive.py
اسکریپت برای استفاده از روش های مناسب با این حال، در بسیاری از موارد، ممکن است به کد منبع مشتری یا کلاس سرویس دسترسی نداشته باشیم. همچنین، این یک مثال ساده است. با مشتریان و سرویسهای بزرگتر، ممکن است در صورت شکستن سازگاری با سایر سیستمها، اصلاح هر یک از آنها امکانپذیر نباشد.
در عوض، میتوانیم از یک آداپتور برای پر کردن شکاف سازگاری بین کد مشتری و شیء سرویس خود استفاده کنیم.
استفاده از آداپتورها برای حل مشکل ناسازگاری
در یک فایل جدید، motorcycle_adapter.py
، کلاس زیر را اضافه کنید:
class MotorcycleAdapter:
def __init__(self, motorcycle):
self.motorcycle = motorcycle
def accelerate(self):
self.motorcycle.rev_throttle()
def apply_brakes(self):
self.motorcycle.pull_brake_lever()
def assign_driver(self, name):
self.motorcycle.assign_rider(name)
یک را ایجاد کردیم MotorcycleAdapter
کلاس، که خود را با یک شیء سرویس (motorcycle
). آداپتور متدهای کلاینت را پیاده سازی می کند accelerate()
، apply_brakes()
و assign_driver()
. داخل بدنه accelerate()
روش، ما استفاده کرده ایم motorcycle
نمونه ای از شی سرویس برای فراخوانی rev_throttle()
روش سرویس به همین ترتیب، روش های دیگر از روش های مربوطه استفاده می کنند Motorcycle
کلاس
حالا بیایید به روز کنیم drive.py
بنابراین ما می توانیم از آداپتور در try/except
مسدود کردن:
from car import Car
from motorcycle import Motorcycle
from motorcycle_adapter import MotorcycleAdapter
import traceback
if __name__ == '__main__':
car = Car()
bike = Motorcycle()
bike_adapter = MotorcycleAdapter(bike)
...
try:
print("Attempting to call client methods with the service object using an adapter\n")
bike_adapter.assign_driver("Robert")
bike_adapter.accelerate()
bike_adapter.apply_brakes()
except AttributeError:
print("Oops! bike object cannot access car methods")
traceback.print_exc()
اینجا،bike_adapter
یک شی از MotorcycleAdapter
کلاس ما عرضه کردیم bike
اعتراض به MotorcycleAdapter
سازنده کلاس اجرای این اسکریپت خروجی زیر را به ما می دهد:
The Motorcycle
Subodh is riding the motorcycle
The speed of the motorcycle is 88 mph
The speed of the motorcycle is 35 mph after applying the brakes
The Car
Sushant is driving the car
The speed of the car is 91 mph
The speed of the car is 24 mph after applying the brakes
Attempting to call client methods with the service object
Attempting to call client methods with the service object using an adapter
Robert is riding the motorcycle
The speed of the motorcycle is 67 mph
The speed of the motorcycle is 25 mph after applying the brakes
بدون نیاز به تنظیم زیربنا Motorcycle
کلاس، ما می توانیم آن را به کار مانند یک Car
با استفاده از آداپتور!
مزایا و معایب الگوی طراحی آداپتور
مزایای الگوهای آداپتور عبارتند از:
- ما می توانیم به جفت کم بین کلاس آداپتور و کلاس مشتری دست یابیم.
- ما میتوانیم از کلاس آداپتور برای گنجاندن کلاسهای خدمات متعدد در برنامه استفاده مجدد کنیم.
- میتوانیم با معرفی چند آداپتور بدون تداخل با کد کلاینت، انعطافپذیری برنامه را افزایش دهیم
معایب الگوی آداپتور عبارتند از:
- پیچیدگی برنامه با اضافه شدن کلاس آداپتور و کلاس سرویس افزایش می یابد.
- با ارسال درخواست ها از یک کلاس به کلاس دیگر، هزینه های سربار در برنامه افزایش می یابد.
- الگوی آداپتور (آداپتور کلاس) از وراثت چندگانه استفاده می کند که ممکن است همه زبان های برنامه نویسی از آن پشتیبانی نکنند.
نتیجه
در این مقاله با الگوی طراحی آداپتور، انواع آن و مشکلات حل آنها آشنا شدیم. ما الگوی Adapter را در پایتون پیاده سازی کردیم تا بتوانیم با a تعامل داشته باشیم Motorcycle
شیء، مانند a Car
با استفاده از یک آداپتور شیء کنید تا رابط هر کلاس تغییر نکند.
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-03 06:58:03