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

Summarize this content to 400 words in Persian Lang
الگوهای طراحی یک جنبه اساسی از مهندسی نرم افزار هستند که راه حل های قابل استفاده مجدد را برای مشکلات رایج در طراحی نرم افزار ارائه می دهند. الگوهای طراحی سازه بر چگونگی ترکیب کلاس ها و اشیاء برای تشکیل ساختارهای بزرگتر تمرکز می کنند. از جمله شناخته شده ترین الگوهای طراحی سازه می توان به آداپتور و کامپوزیت الگوها
در این مقاله، این دو الگوی طراحی را به طور عمیق بررسی خواهیم کرد، موارد استفاده، پیاده سازی و مزایای آنها را درک خواهیم کرد.
1. الگوی طراحی آداپتور
نمای کلی:
را آداپتور الگوی طراحی زمانی استفاده می شود که می خواهید یک کلاس موجود را با یک سیستم جدید ادغام کنید اما رابط کلاس موجود با آنچه سیستم جدید نیاز دارد مطابقت ندارد. آداپتور به عنوان یک پل بین دو رابط ناسازگار عمل می کند و به آنها اجازه می دهد با هم کار کنند.
مورد استفاده:
سناریویی را در نظر بگیرید که در آن شما یک کتابخانه شخص ثالث یا یک سیستم قدیمی دارید که نمی توانید آن را تغییر دهید، اما باید آن را با کد فعلی خود ادغام کنید. کد شخص ثالث ممکن است دارای امضای روش یا رابط متفاوتی با آنچه سیستم شما انتظار دارد داشته باشد. الگوی Adapter شما را قادر می سازد تا کد موجود را برای برآورده کردن نیازهای سیستم جدید بدون تغییر کد اصلی “تطبیق دهید”.
اجزای کلیدی:
مشتری: سیستم یا برنامه ای که به عملکرد مورد نظر نیاز دارد اما انتظار یک رابط خاص را دارد.
سازگار: کلاس یا سیستم موجود که عملکرد را ارائه می دهد اما با رابط مورد نیاز مطابقت ندارد.
آداپتور: کلاسی که رابط Adaptee را به کلاسی تبدیل می کند که Client انتظار دارد.
مثال:
فرض کنید یک کلاس موجود داریم که پرداختها را از طریق PayPal انجام میدهد، اما اکنون باید آن را در سیستمی ادغام کنیم که انتظار یک رابط پرداخت Stripe را دارد. در اینجا نحوه طراحی آداپتور می تواند کمک کند:
// Adaptee: The existing PayPal payment system
class PayPalPayment {
pay(amount) {
console.log(`Paying $${amount} using PayPal.`);
}
}
// Target Interface: The system expects a Stripe-like payment interface
class StripePayment {
processPayment(amount) {
console.log(`Paying $${amount} using Stripe.`);
}
}
// Adapter: Adapts PayPal to Stripe’s interface
class PayPalAdapter extends StripePayment {
constructor(paypal) {
super();
this.paypal = paypal;
}
processPayment(amount) {
this.paypal.pay(amount);
}
}
// Client: Works with the StripePayment interface
const paymentSystem = new PayPalAdapter(new PayPalPayment());
paymentSystem.processPayment(100);
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مزایای الگوی آداپتور:
انعطاف پذیری: میتوانید از کلاسهای موجود بدون تغییر کد آنها استفاده مجدد کنید، که هنگام کار با کتابخانههای شخص ثالث مفید است.
اصل مسئولیت واحد: الگوی آداپتور امکان جداسازی واضح نگرانی ها را فراهم می کند. آداپتور بر تبدیل رابط ها تمرکز می کند، در حالی که مشتری و Adaptee نقش های مربوطه خود را انجام می دهند.
کوپلینگ شل: Client و Adaptee به طور ضعیفی جفت می شوند و به شما امکان می دهند اجزا را به راحتی جایگزین یا ارتقا دهید.
زمان استفاده:
زمانی که باید کدهای قدیمی را در یک سیستم جدید ادغام کنید.
زمانی که سیستم شما انتظار یک رابط خاص را دارد اما جزء موجود آن را ارائه نمی دهد.
2. الگوی طراحی ترکیبی
نمای کلی:
را کامپوزیت الگوی طراحی زمانی استفاده می شود که شما نیاز دارید با اشیا و ترکیبات اشیا به طور یکنواخت رفتار کنید. این الگو به شما امکان می دهد ساختارهای درخت مانندی بسازید که نشان دهنده سلسله مراتب بخشی از کل است، جایی که هم اشیاء برگ و هم اشیاء مرکب توسط مشتری یکسان رفتار می کنند.
مورد استفاده:
تصور کنید در حال طراحی یک ویرایشگر گرافیکی هستید که در آن کاربران می توانند اشکال اصلی (مانند دایره و مستطیل) را ترسیم کرده و آنها را به شکل های پیچیده تر ترکیب کنند. یک شکل پیچیده از اشکال منفرد تشکیل شده است، اما شما می خواهید هر دو شکل فردی و ترکیبی را به یک شکل رفتار کنید.
اجزای کلیدی:
جزء: رابطی که عملیات مشترک را هم برای اشیاء مجزا و هم برای کامپوزیت ها اعلام می کند.
برگ: اشیاء مجزا که رابط Component را پیاده سازی می کنند. اینها بلوک های اصلی ساختمان هستند (به عنوان مثال، یک شکل).
کامپوزیت: جسمی که چندین شیء برگ را در خود جای می دهد. Composite همچنین رابط Component را پیادهسازی میکند و به مشتری اجازه میدهد به عنوان یک شی Leaf در نظر گرفته شود.
مثال:
بیایید مثال ویرایشگر گرافیکی را در نظر بگیریم که در آن میخواهیم هر دو شکل فردی و گروهی از اشکال را به طور یکنواخت بررسی کنیم:
// Component: The common interface for individual and composite objects
class Graphic {
draw() {}
}
// Leaf: Represents individual shapes
class Circle extends Graphic {
draw() {
console.log(“Drawing a Circle”);
}
}
class Rectangle extends Graphic {
draw() {
console.log(“Drawing a Rectangle”);
}
}
// Composite: Represents groups of shapes
class CompositeGraphic extends Graphic {
constructor() {
super();
this.graphics = [];
}
add(graphic) {
this.graphics.push(graphic);
}
remove(graphic) {
this.graphics = this.graphics.filter(g => g !== graphic);
}
draw() {
for (const graphic of this.graphics) {
graphic.draw();
}
}
}
// Client: Works with both individual and composite objects
const circle = new Circle();
const rectangle = new Rectangle();
const composite = new CompositeGraphic();
composite.add(circle);
composite.add(rectangle);
composite.draw(); // Output: Drawing a Circle, Drawing a Rectangle
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مزایای الگوی ترکیبی:
یکنواختی: الگوی ترکیبی به مشتریان اجازه می دهد تا با اشیاء و ترکیبات فردی به طور یکنواخت رفتار کنند. شما می توانید هر دو شی Leaf و Composite را به یک شکل بدون نوشتن کد شرطی مدیریت کنید.
کد مشتری را ساده می کند: از آنجایی که اشیاء منفرد و اشیاء ترکیبی یک رابط مشترک دارند، مدیریت کد مشتری سادهتر و آسانتر میشود.
توسعه پذیری: گسترش سیستم با افزودن اجزای Leaf یا Composite جدید بدون تأثیر بر کد مشتری آسان است.
زمان استفاده:
هنگامی که شما نیاز به نمایش سلسله مراتب بخشی از کل، مانند فایل ها و پوشه ها در یک سیستم فایل یا اشکال در یک ویرایشگر گرافیکی دارید.
زمانی که می خواهید مشتریان با اشیاء و ترکیبات فردی به طور یکنواخت رفتار کنند.
نتیجه گیری
هر دو آداپتور و کامپوزیت الگوهای طراحی ابزارهای ضروری در توسعه نرم افزار هستند، به ویژه در سناریوهایی که انعطاف پذیری و یکنواختی مورد نیاز است.
آداپتور زمانی ایدهآل است که نیاز به ادغام رابطهای ناسازگار بدون تغییر کد موجود دارید، و در سیستمهایی که با کدهای قدیمی یا کتابخانههای شخص ثالث کار میکنید مفید است.
کامپوزیت زمانی مفید است که شما نیاز به کار با ساختارهای درخت مانند یا سلسله مراتب جزئی کل دارید و به شما این امکان را می دهد که با اشیاء و ترکیبات فردی به روشی یکپارچه رفتار کنید.
این الگوها می توانند به طور قابل توجهی قابلیت نگهداری، انعطاف پذیری و مقیاس پذیری برنامه های شما را بهبود بخشند و آنها را برای ساختن سیستم های نرم افزاری قوی بسیار مهم می کنند. درک و پیادهسازی این الگوها میتواند مهارتهای طراحی شما را بالا ببرد و شما را در حل مشکلات ساختاری کدتان موثرتر کند.
الگوهای طراحی یک جنبه اساسی از مهندسی نرم افزار هستند که راه حل های قابل استفاده مجدد را برای مشکلات رایج در طراحی نرم افزار ارائه می دهند. الگوهای طراحی سازه بر چگونگی ترکیب کلاس ها و اشیاء برای تشکیل ساختارهای بزرگتر تمرکز می کنند. از جمله شناخته شده ترین الگوهای طراحی سازه می توان به آداپتور و کامپوزیت الگوها
در این مقاله، این دو الگوی طراحی را به طور عمیق بررسی خواهیم کرد، موارد استفاده، پیاده سازی و مزایای آنها را درک خواهیم کرد.
1. الگوی طراحی آداپتور
نمای کلی:
را آداپتور الگوی طراحی زمانی استفاده می شود که می خواهید یک کلاس موجود را با یک سیستم جدید ادغام کنید اما رابط کلاس موجود با آنچه سیستم جدید نیاز دارد مطابقت ندارد. آداپتور به عنوان یک پل بین دو رابط ناسازگار عمل می کند و به آنها اجازه می دهد با هم کار کنند.
مورد استفاده:
سناریویی را در نظر بگیرید که در آن شما یک کتابخانه شخص ثالث یا یک سیستم قدیمی دارید که نمی توانید آن را تغییر دهید، اما باید آن را با کد فعلی خود ادغام کنید. کد شخص ثالث ممکن است دارای امضای روش یا رابط متفاوتی با آنچه سیستم شما انتظار دارد داشته باشد. الگوی Adapter شما را قادر می سازد تا کد موجود را برای برآورده کردن نیازهای سیستم جدید بدون تغییر کد اصلی “تطبیق دهید”.
اجزای کلیدی:
- مشتری: سیستم یا برنامه ای که به عملکرد مورد نظر نیاز دارد اما انتظار یک رابط خاص را دارد.
- سازگار: کلاس یا سیستم موجود که عملکرد را ارائه می دهد اما با رابط مورد نیاز مطابقت ندارد.
- آداپتور: کلاسی که رابط Adaptee را به کلاسی تبدیل می کند که Client انتظار دارد.
مثال:
فرض کنید یک کلاس موجود داریم که پرداختها را از طریق PayPal انجام میدهد، اما اکنون باید آن را در سیستمی ادغام کنیم که انتظار یک رابط پرداخت Stripe را دارد. در اینجا نحوه طراحی آداپتور می تواند کمک کند:
// Adaptee: The existing PayPal payment system
class PayPalPayment {
pay(amount) {
console.log(`Paying $${amount} using PayPal.`);
}
}
// Target Interface: The system expects a Stripe-like payment interface
class StripePayment {
processPayment(amount) {
console.log(`Paying $${amount} using Stripe.`);
}
}
// Adapter: Adapts PayPal to Stripe's interface
class PayPalAdapter extends StripePayment {
constructor(paypal) {
super();
this.paypal = paypal;
}
processPayment(amount) {
this.paypal.pay(amount);
}
}
// Client: Works with the StripePayment interface
const paymentSystem = new PayPalAdapter(new PayPalPayment());
paymentSystem.processPayment(100);
مزایای الگوی آداپتور:
- انعطاف پذیری: میتوانید از کلاسهای موجود بدون تغییر کد آنها استفاده مجدد کنید، که هنگام کار با کتابخانههای شخص ثالث مفید است.
- اصل مسئولیت واحد: الگوی آداپتور امکان جداسازی واضح نگرانی ها را فراهم می کند. آداپتور بر تبدیل رابط ها تمرکز می کند، در حالی که مشتری و Adaptee نقش های مربوطه خود را انجام می دهند.
- کوپلینگ شل: Client و Adaptee به طور ضعیفی جفت می شوند و به شما امکان می دهند اجزا را به راحتی جایگزین یا ارتقا دهید.
زمان استفاده:
- زمانی که باید کدهای قدیمی را در یک سیستم جدید ادغام کنید.
- زمانی که سیستم شما انتظار یک رابط خاص را دارد اما جزء موجود آن را ارائه نمی دهد.
2. الگوی طراحی ترکیبی
نمای کلی:
را کامپوزیت الگوی طراحی زمانی استفاده می شود که شما نیاز دارید با اشیا و ترکیبات اشیا به طور یکنواخت رفتار کنید. این الگو به شما امکان می دهد ساختارهای درخت مانندی بسازید که نشان دهنده سلسله مراتب بخشی از کل است، جایی که هم اشیاء برگ و هم اشیاء مرکب توسط مشتری یکسان رفتار می کنند.
مورد استفاده:
تصور کنید در حال طراحی یک ویرایشگر گرافیکی هستید که در آن کاربران می توانند اشکال اصلی (مانند دایره و مستطیل) را ترسیم کرده و آنها را به شکل های پیچیده تر ترکیب کنند. یک شکل پیچیده از اشکال منفرد تشکیل شده است، اما شما می خواهید هر دو شکل فردی و ترکیبی را به یک شکل رفتار کنید.
اجزای کلیدی:
- جزء: رابطی که عملیات مشترک را هم برای اشیاء مجزا و هم برای کامپوزیت ها اعلام می کند.
- برگ: اشیاء مجزا که رابط Component را پیاده سازی می کنند. اینها بلوک های اصلی ساختمان هستند (به عنوان مثال، یک شکل).
- کامپوزیت: جسمی که چندین شیء برگ را در خود جای می دهد. Composite همچنین رابط Component را پیادهسازی میکند و به مشتری اجازه میدهد به عنوان یک شی Leaf در نظر گرفته شود.
مثال:
بیایید مثال ویرایشگر گرافیکی را در نظر بگیریم که در آن میخواهیم هر دو شکل فردی و گروهی از اشکال را به طور یکنواخت بررسی کنیم:
// Component: The common interface for individual and composite objects
class Graphic {
draw() {}
}
// Leaf: Represents individual shapes
class Circle extends Graphic {
draw() {
console.log("Drawing a Circle");
}
}
class Rectangle extends Graphic {
draw() {
console.log("Drawing a Rectangle");
}
}
// Composite: Represents groups of shapes
class CompositeGraphic extends Graphic {
constructor() {
super();
this.graphics = [];
}
add(graphic) {
this.graphics.push(graphic);
}
remove(graphic) {
this.graphics = this.graphics.filter(g => g !== graphic);
}
draw() {
for (const graphic of this.graphics) {
graphic.draw();
}
}
}
// Client: Works with both individual and composite objects
const circle = new Circle();
const rectangle = new Rectangle();
const composite = new CompositeGraphic();
composite.add(circle);
composite.add(rectangle);
composite.draw(); // Output: Drawing a Circle, Drawing a Rectangle
مزایای الگوی ترکیبی:
- یکنواختی: الگوی ترکیبی به مشتریان اجازه می دهد تا با اشیاء و ترکیبات فردی به طور یکنواخت رفتار کنند. شما می توانید هر دو شی Leaf و Composite را به یک شکل بدون نوشتن کد شرطی مدیریت کنید.
- کد مشتری را ساده می کند: از آنجایی که اشیاء منفرد و اشیاء ترکیبی یک رابط مشترک دارند، مدیریت کد مشتری سادهتر و آسانتر میشود.
- توسعه پذیری: گسترش سیستم با افزودن اجزای Leaf یا Composite جدید بدون تأثیر بر کد مشتری آسان است.
زمان استفاده:
- هنگامی که شما نیاز به نمایش سلسله مراتب بخشی از کل، مانند فایل ها و پوشه ها در یک سیستم فایل یا اشکال در یک ویرایشگر گرافیکی دارید.
- زمانی که می خواهید مشتریان با اشیاء و ترکیبات فردی به طور یکنواخت رفتار کنند.
نتیجه گیری
هر دو آداپتور و کامپوزیت الگوهای طراحی ابزارهای ضروری در توسعه نرم افزار هستند، به ویژه در سناریوهایی که انعطاف پذیری و یکنواختی مورد نیاز است.
-
آداپتور زمانی ایدهآل است که نیاز به ادغام رابطهای ناسازگار بدون تغییر کد موجود دارید، و در سیستمهایی که با کدهای قدیمی یا کتابخانههای شخص ثالث کار میکنید مفید است.
-
کامپوزیت زمانی مفید است که شما نیاز به کار با ساختارهای درخت مانند یا سلسله مراتب جزئی کل دارید و به شما این امکان را می دهد که با اشیاء و ترکیبات فردی به روشی یکپارچه رفتار کنید.
این الگوها می توانند به طور قابل توجهی قابلیت نگهداری، انعطاف پذیری و مقیاس پذیری برنامه های شما را بهبود بخشند و آنها را برای ساختن سیستم های نرم افزاری قوی بسیار مهم می کنند. درک و پیادهسازی این الگوها میتواند مهارتهای طراحی شما را بالا ببرد و شما را در حل مشکلات ساختاری کدتان موثرتر کند.