
مسئلہ کے بارے میں مزید
سب سے پہلے، ہم پرانے نظام کے رویے کی نقل کریں گے۔ فرض کریں کہ یہ کام یا اسکول میں دیر سے آنے کا بہانہ بناتا ہے۔ ایسا کرنے کے لیے، اس کا ایکExcuse
انٹرفیس ہے جس میں generateExcuse()
اور طریقے ہیں likeExcuse()
۔dislikeExcuse()
public interface Excuse {
String generateExcuse();
void likeExcuse(String excuse);
void dislikeExcuse(String excuse);
}
کلاس WorkExcuse
اس انٹرفیس کو نافذ کرتی ہے:
public class WorkExcuse implements Excuse {
private String[] excuses = {"in an incredible confluence of circumstances, I ran out of hot water and had to wait until sunlight, focused using a magnifying glass, heated a mug of water so that I could wash.",
"the artificial intelligence in my alarm clock failed me, waking me up an hour earlier than normal. Because it is winter, I thought it was still nighttime and I fell back asleep. Everything after that is a bit hazy.",
"my pre-holiday mood slows metabolic processes in my body, leading to depression and insomnia."};
private String [] apologies = {"This will not happen again, of course. I'm very sorry.", "I apologize for my unprofessional behavior.", "There is no excuse for my actions. I am not worthy of this position."};
@Override
public String generateExcuse() { // Randomly select an excuse from the array
String result = "I was late today because " + excuses[(int) Math.round(Math.random() + 1)] + "\\n" +
apologies[(int) Math.round(Math.random() + 1)];
return result;
}
@Override
public void likeExcuse(String excuse) {
// Duplicate the element in the array so that its chances of being chosen are higher
}
@Override
public void dislikeExcuse(String excuse) {
// Remove the item from the array
}
}
آئیے اپنی مثال کی جانچ کریں:
Excuse excuse = new WorkExcuse();
System.out.println(excuse.generateExcuse());
آؤٹ پٹ:
"I was late today because my pre-holiday mood slows metabolic processes in my body, leading to depression and insomnia.
I apologize for my unprofessional behavior.
اب تصور کریں کہ آپ نے ایک عذر پیدا کرنے والی سروس شروع کی ہے، اعداد و شمار جمع کیے ہیں، اور محسوس کیا ہے کہ آپ کے زیادہ تر صارفین یونیورسٹی کے طالب علم ہیں۔ اس گروپ کو بہتر طریقے سے خدمت کرنے کے لیے، آپ نے ایک دوسرے ڈویلپر سے ایک ایسا نظام بنانے کو کہا جو خاص طور پر یونیورسٹی کے طلباء کے لیے بہانے پیدا کرے۔ ترقیاتی ٹیم نے مارکیٹ ریسرچ کی، بہانے درجہ بندی کی، کچھ مصنوعی ذہانت کو جوڑ دیا، اور سروس کو ٹریفک رپورٹس، موسم کی رپورٹس وغیرہ کے ساتھ مربوط کیا۔ اب آپ کے پاس یونیورسٹی کے طلباء کے لیے بہانے پیدا کرنے کے لیے ایک لائبریری ہے، لیکن اس کا انٹرفیس مختلف ہے: StudentExcuse
.
public interface StudentExcuse {
String generateExcuse();
void dislikeExcuse(String excuse);
}
اس انٹرفیس کے دو طریقے ہیں:، generateExcuse
جو ایک عذر پیدا کرتا ہے، اور dislikeExcuse
، جو عذر کو مستقبل میں دوبارہ ظاہر ہونے سے روکتا ہے۔ تھرڈ پارٹی لائبریری میں ترمیم نہیں کی جا سکتی، یعنی آپ اس کا سورس کوڈ تبدیل نہیں کر سکتے۔ اب ہمارے پاس ایک ایسا نظام ہے جس میں دو کلاسز ہیں جو Excuse
انٹرفیس کو نافذ کرتی ہیں، اور ایک لائبریری جس میں ایک SuperStudentExcuse
کلاس ہے جو StudentExcuse
انٹرفیس کو نافذ کرتی ہے:
public class SuperStudentExcuse implements StudentExcuse {
@Override
public String generateExcuse() {
// Logic for the new functionality
return "An incredible excuse adapted to the current weather conditions, traffic jams, or delays in public transport schedules.";
}
@Override
public void dislikeExcuse(String excuse) {
// Adds the reason to a blacklist
}
}
کوڈ کو تبدیل نہیں کیا جا سکتا۔ موجودہ طبقاتی درجہ بندی اس طرح نظر آتی ہے: 

Excuse
انٹرفیس کا نام تبدیل کرنا ہوگا۔ لیکن سنجیدہ ایپلی کیشنز میں اضافی درجہ بندی ناپسندیدہ ہے: ایک عام جڑ عنصر متعارف کرانے سے فن تعمیر ٹوٹ جاتا ہے۔ آپ کو ایک انٹرمیڈیٹ کلاس لاگو کرنا چاہئے جو ہمیں کم سے کم نقصانات کے ساتھ نئی اور پرانی دونوں فعالیتوں کو استعمال کرنے دے گی۔ مختصر میں، آپ کو ایک اڈاپٹر کی ضرورت ہے .
اڈاپٹر پیٹرن کے پیچھے اصول
ایک اڈاپٹر ایک انٹرمیڈیٹ آبجیکٹ ہے جو ایک آبجیکٹ کی میتھڈ کالز کو دوسرے کو سمجھنے کی اجازت دیتا ہے۔ آئیے اپنی مثال کے لیے ایک اڈاپٹر نافذ کریں اور اسے کال کریںMiddleware
۔ ہمارے اڈاپٹر کو ایک ایسا انٹرفیس نافذ کرنا چاہیے جو کسی ایک چیز کے ساتھ مطابقت رکھتا ہو۔ رہنے دو Excuse
. یہ Middleware
پہلی چیز کے طریقوں کو کال کرنے کی اجازت دیتا ہے۔ Middleware
کالز وصول کرتا ہے اور انہیں مطابقت پذیر طریقے سے دوسرے آبجیکٹ پر بھیجتا ہے۔ یہاں اور طریقوں Middleware
کے ساتھ عمل درآمد ہے : generateExcuse
dislikeExcuse
public class Middleware implements Excuse { // 1. Middleware becomes compatible with WorkExcuse objects via the Excuse interface
private StudentExcuse superStudentExcuse;
public Middleware(StudentExcuse excuse) { // 2. Get a reference to the object being adapted
this.superStudentExcuse = excuse;
}
@Override
public String generateExcuse() {
return superStudentExcuse.generateExcuse(); // 3. The adapter implements an interface method
}
@Override
public void dislikeExcuse(String excuse) {
// The method first adds the excuse to the blacklist,
// Then passes it to the dislikeExcuse method of the superStudentExcuse object.
}
// The likeExcuse method will appear later
}
ٹیسٹنگ (کلائنٹ کوڈ میں):
public class Test {
public static void main(String[] args) {
Excuse excuse = new WorkExcuse(); // We create objects of the classes
StudentExcuse newExcuse = new SuperStudentExcuse(); // that must be compatible.
System.out.println("An ordinary excuse for an employee:");
System.out.println(excuse.generateExcuse());
System.out.println("\n");
Excuse adaptedStudentExcuse = new Middleware(newExcuse); // Wrap the new functionality in the adapter object
System.out.println("Using new functionality with the adapter:");
System.out.println(adaptedStudentExcuse.generateExcuse()); // The adapter calls the adapted method
}
}
آؤٹ پٹ:
An ordinary excuse for an employee:
I was late today because my pre-holiday mood slows metabolic processes in my body, leading to depression and insomnia.
There is no excuse for my actions. I am not worthy of this position.
Using new functionality with the adapter:
موجودہ موسمی حالات، ٹریفک جام، یا پبلک ٹرانسپورٹ کے نظام الاوقات میں تاخیر کے مطابق ایک ناقابل یقین عذر۔ یہ generateExcuse
طریقہ بغیر کسی اضافی تبدیلی کے، کال کو کسی اور چیز تک پہنچاتا ہے۔ طریقہ dislikeExcuse
کار کے لیے ہمیں پہلے عذر کو بلیک لسٹ کرنے کی ضرورت تھی۔ انٹرمیڈیٹ ڈیٹا پروسیسنگ انجام دینے کی صلاحیت ایک وجہ ہے کہ لوگ اڈاپٹر پیٹرن کو پسند کرتے ہیں۔ لیکن اس likeExcuse
طریقہ کا کیا ہوگا، جو Excuse
انٹرفیس کا حصہ ہے لیکن StudentExcuse
انٹرفیس کا حصہ نہیں ہے؟ نئی فعالیت اس آپریشن کی حمایت نہیں کرتی ہے۔ UnsupportedOperationException
اس صورت حال کے لئے ایجاد کیا گیا تھا . اگر مطلوبہ آپریشن تعاون یافتہ نہیں ہے تو اسے پھینک دیا جاتا ہے۔ آئیے اسے استعمال کریں۔ Middleware
کلاس کا نیا نفاذ اس طرح دکھتا ہے:
public class Middleware implements Excuse {
private StudentExcuse superStudentExcuse;
public Middleware(StudentExcuse excuse) {
this.superStudentExcuse = excuse;
}
@Override
public String generateExcuse() {
return superStudentExcuse.generateExcuse();
}
@Override
public void likeExcuse(String excuse) {
throw new UnsupportedOperationException("The likeExcuse method is not supported by the new functionality");
}
@Override
public void dislikeExcuse(String excuse) {
// The method accesses a database to fetch additional information,
// and then passes it to the superStudentExcuse object's dislikeExcuse method.
}
}
پہلی نظر میں، یہ حل بہت اچھا نہیں لگتا، لیکن فعالیت کی نقل کرنا صورتحال کو پیچیدہ بنا سکتا ہے۔ اگر کلائنٹ توجہ دیتا ہے، اور اڈاپٹر اچھی طرح سے دستاویزی ہے، تو اس طرح کا حل قابل قبول ہے.
اڈاپٹر کب استعمال کریں۔
-
جب آپ کو تھرڈ پارٹی کلاس استعمال کرنے کی ضرورت ہو، لیکن اس کا انٹرفیس مرکزی ایپلیکیشن سے مطابقت نہیں رکھتا۔ اوپر دی گئی مثال سے پتہ چلتا ہے کہ ایک اڈاپٹر آبجیکٹ کیسے بنایا جائے جو کالز کو اس فارمیٹ میں لپیٹے جسے کوئی ہدف آبجیکٹ سمجھ سکے۔
-
جب کئی موجودہ ذیلی طبقات کو کچھ مشترکہ فعالیت کی ضرورت ہوتی ہے۔ اضافی ذیلی طبقات (جو کوڈ کی نقل کا باعث بنے گا) بنانے کے بجائے، اڈاپٹر کا استعمال کرنا بہتر ہے۔
فائدے اور نقصانات
فائدہ: اڈاپٹر کلائنٹ سے ایک آبجیکٹ سے دوسری چیز پر کارروائی کی درخواستوں کی تفصیلات چھپاتا ہے۔ کلائنٹ کوڈ ڈیٹا کو فارمیٹ کرنے یا ٹارگٹ میتھڈ پر کالوں کو ہینڈل کرنے کے بارے میں نہیں سوچتا ہے۔ یہ بہت پیچیدہ ہے، اور پروگرامرز سست ہیں :) نقصان: پروجیکٹ کا کوڈ بیس اضافی کلاسوں سے پیچیدہ ہے۔ اگر آپ کے پاس بہت زیادہ متضاد انٹرفیس ہیں، تو اضافی کلاسوں کی تعداد غیر منظم ہو سکتی ہے۔اڈاپٹر کو اگواڑے یا ڈیکوریٹر کے ساتھ الجھائیں نہیں۔
صرف سطحی معائنہ کے ساتھ، ایک اڈاپٹر اگواڑے اور سجاوٹ کے نمونوں کے ساتھ الجھ سکتا ہے۔ اڈاپٹر اور اگواڑے کے درمیان فرق یہ ہے کہ اگواڑا ایک نیا انٹرفیس متعارف کراتا ہے اور پورے سب سسٹم کو لپیٹ دیتا ہے۔ اور ڈیکوریٹر، اڈاپٹر کے برعکس، انٹرفیس کی بجائے آبجیکٹ کو خود ہی تبدیل کرتا ہے۔مرحلہ وار الگورتھم
-
سب سے پہلے، یقینی بنائیں کہ آپ کے پاس کوئی مسئلہ ہے جسے یہ پیٹرن حل کر سکتا ہے۔
-
کلائنٹ انٹرفیس کی وضاحت کریں جو غیر مطابقت پذیر اشیاء کے ساتھ بالواسطہ تعامل کے لیے استعمال کیا جائے گا۔
-
اڈاپٹر کلاس کو پچھلے مرحلے میں بیان کردہ انٹرفیس کا وارث بنائیں۔
-
اڈاپٹر کلاس میں، اڈاپٹی آبجیکٹ کا حوالہ ذخیرہ کرنے کے لیے ایک فیلڈ بنائیں۔ یہ حوالہ کنسٹرکٹر کو دیا جاتا ہے۔
-
اڈاپٹر میں کلائنٹ کے تمام انٹرفیس طریقوں کو لاگو کریں۔ ایک طریقہ ہو سکتا ہے:
-
بغیر کسی تبدیلی کے کالز پاس کریں۔
-
ڈیٹا میں ترمیم یا اضافہ کریں، ٹارگٹ میتھڈ پر کالز کی تعداد میں اضافہ/کم کریں، وغیرہ۔
-
انتہائی صورتوں میں، اگر کوئی خاص طریقہ مطابقت نہیں رکھتا ہے، تو ایک UnsupportedOperationException پھینک دیں۔ غیر تعاون یافتہ آپریشنز کو سختی سے دستاویزی ہونا چاہیے۔
-
-
اگر ایپلی کیشن کلائنٹ انٹرفیس کے ذریعے صرف اڈاپٹر کلاس کا استعمال کرتی ہے (جیسا کہ اوپر کی مثال میں)، تو اڈاپٹر کو مستقبل میں بغیر کسی تکلیف کے بڑھایا جا سکتا ہے۔
GO TO FULL VERSION