توهان کي پراکسي جي ضرورت ڇو آهي؟
اهو نمونو هڪ اعتراض تائين ڪنٽرول رسائي سان لاڳاپيل مسئلن کي حل ڪرڻ ۾ مدد ڪري ٿو. توھان پڇي سگھو ٿا، "ڇو اسان کي ڪنٽرول رسائي جي ضرورت آھي؟" اچو ته ڪجهه حالتن تي نظر رکون جيڪي توهان جي مدد ڪندا ته ڇا آهي.مثال 1
تصور ڪريو ته اسان وٽ ھڪڙو وڏو پراجيڪٽ آھي پراڻو ڪوڊ جي ھڪڙي گروپ سان، جتي ھڪڙو ڪلاس آھي جيڪو ڊيٽابيس مان رپورٽون برآمد ڪرڻ جو ذميوار آھي. ڪلاس هم وقت ڪم ڪري ٿو. اهو آهي، سڄو سسٽم بيڪار آهي جڏهن ته ڊيٽابيس درخواست تي عمل ڪري ٿو. سراسري طور تي، هڪ رپورٽ ٺاهڻ ۾ 30 منٽ لڳن ٿا. ان مطابق، برآمد جو عمل 12:30 AM تي شروع ٿئي ٿو، ۽ انتظاميا صبح جو رپورٽ حاصل ڪري ٿي. هڪ آڊٽ انڪشاف ڪيو ته اهو بهتر هوندو ته فوري طور تي عام ڪاروباري ڪلاڪن دوران رپورٽ حاصل ڪري سگهجي. شروعاتي وقت کي ملتوي نه ٿو ڪري سگھجي، ۽ سسٽم بلاڪ نه ٿو ڪري سگھي جڏھن اھو ڊيٽابيس مان جواب جو انتظار ڪري. حل اهو آهي ته تبديل ڪيو وڃي ته سسٽم ڪيئن ڪم ڪري ٿو، هڪ الڳ موضوع تي رپورٽ پيدا ڪرڻ ۽ برآمد ڪرڻ. اهو حل سسٽم کي معمول وانگر ڪم ڪرڻ ڏيندو، ۽ انتظاميا تازيون رپورٽون وصول ڪندي. بهرحال، اتي هڪ مسئلو آهي: موجوده ڪوڊ ٻيهر نه ٿو لکي سگھجي، ڇاڪاڻ ته سسٽم جا ٻيا حصا ان جي ڪارڪردگي کي استعمال ڪن ٿا. انهي صورت ۾، اسان هڪ وچولي پراکسي ڪلاس متعارف ڪرائڻ لاءِ پراکسي نمون استعمال ڪري سگهون ٿا جيڪو رپورٽون برآمد ڪرڻ لاءِ درخواستون وصول ڪندو، شروعاتي وقت کي لاگ ان ڪري، ۽ هڪ الڳ ٿريڊ شروع ڪندو. هڪ دفعو رپورٽ ٺاهي وئي، موضوع ختم ٿي ويو ۽ هرڪو خوش آهي.مثال 2
هڪ ترقياتي ٽيم ٺاهيندي آهي واقعن جي ويب سائيٽ. نون واقعن تي ڊيٽا حاصل ڪرڻ لاءِ، ٽيم ٽئين پارٽي جي خدمت کان سوال ڪري ٿي. هڪ خاص خانگي لائبريري سروس سان رابطي کي آسان بڻائي ٿي. ترقي جي دوران، هڪ مسئلو دريافت ڪيو ويو آهي: ٽئين پارٽي سسٽم پنهنجي ڊيٽا کي هڪ ڏينهن ۾ هڪ ڀيرو تازه ڪاري ڪري ٿو، پر هڪ درخواست موڪلي وئي آهي ان کي هر وقت جڏهن صارف هڪ صفحي کي تازو ڪري ٿو. هي درخواستن جو هڪ وڏو تعداد ٺاهي ٿو، ۽ خدمت جواب ڏيڻ بند ڪري ٿي. حل اهو آهي ته خدمت جي جواب کي ڪيش ڪيو وڃي ۽ ڪيش ڪيل نتيجن کي گهمڻ وارن ڏانهن واپس ڪيو وڃي جيئن صفحا ٻيهر لوڊ ڪيا وڃن، ڪيش کي اپڊيٽ ڪرڻ جي ضرورت مطابق. انهي حالت ۾، پراکسي ڊيزائن جو نمونو هڪ بهترين حل آهي جيڪو موجوده ڪارڪردگي کي تبديل نٿو ڪري.ڊزائن جي نموني جي پويان اصول
ھن نموني کي لاڳو ڪرڻ لاء، توھان کي ھڪڙو پراکسي ڪلاس ٺاھڻ جي ضرورت آھي. اهو سروس ڪلاس جي انٽرفيس کي لاڳو ڪري ٿو، ڪلائنٽ ڪوڊ لاءِ ان جي رويي کي نقل ڪندي. هن طريقي سان، ڪلائنٽ حقيقي اعتراض جي بدران پراکسي سان رابطو ڪري ٿو. ضابطي جي طور تي، سڀني درخواستن تي گذري ويا آهن خدمت طبقي تي، پر اضافي عملن سان اڳ يا بعد ۾. بس ڪر، هڪ پراکسي ڪلائنٽ ڪوڊ ۽ ٽارگيٽ اعتراض جي وچ ۾ هڪ پرت آهي. هڪ پراڻي ۽ تمام سست هارڊ ڊسڪ مان ڪيشنگ سوال جي نتيجن جي مثال تي غور ڪريو. فرض ڪريو اسان ڪجھ قديم ايپ ۾ برقي ٽرينن جي ٽائم ٽيبل جي باري ۾ ڳالهائي رهيا آهيون جنهن جي منطق کي تبديل نٿو ڪري سگهجي. هڪ ڊسڪ هڪ اپڊيٽ ٽائيم ٽيبل سان هر روز هڪ مقرر وقت تي داخل ڪيو ويندو آهي. تنهن ڪري، اسان وٽ آهي:TrainTimetable
انٽرفيس.ElectricTrainTimetable
، جيڪو هن انٽرفيس کي لاڳو ڪري ٿو.- ڪلائنٽ ڪوڊ هن ڪلاس ذريعي فائل سسٽم سان رابطو ڪري ٿو.
TimetableDisplay
ڪلائنٽ ڪلاس. ان جوprintTimetable()
طريقو طبقن جي طريقن کي استعمال ڪري ٿوElectricTrainTimetable
.

printTimetable()
طريقي جي هر ڪال سان، ElectricTrainTimetable
ڪلاس ڊسڪ تائين رسائي ڪري ٿو، ڊيٽا لوڊ ڪري ٿو، ۽ ڪلائنٽ کي پيش ڪري ٿو. سسٽم ٺيڪ ڪم ڪري ٿو، پر اهو تمام سست آهي. نتيجي طور، فيصلو ڪيو ويو ته سسٽم جي ڪارڪردگي کي وڌائڻ لاء ڪيچنگ ميڪانيزم شامل ڪندي. اهو پراکسي نموني استعمال ڪندي ڪري سگهجي ٿو: 
TimetableDisplay
ڪلاس اهو به نوٽيس نٿو ڪري ته اهو ElectricTrainTimetableProxy
پراڻي طبقي جي بدران طبقي سان لهه وچڙ ۾ آهي. نئون نفاذ ڏينهن ۾ هڪ ڀيرو ٽائيم ٽيبل لوڊ ڪري ٿو. ورجائي درخواستن لاءِ، اهو ميموري مان اڳئين لوڊ ٿيل اعتراض موٽائي ٿو.
پراکسي لاءِ ڪهڙا ڪم بهترين آهن؟
هتي ڪجھ حالتون آهن جتي هي نمونو ضرور هٿ ۾ ايندو:- ڪيشنگ
- دير، يا سست، شروعات ڇو هڪ شئي کي فوري طور تي لوڊ ڪريو جيڪڏهن توهان ان کي ضرورت مطابق لوڊ ڪري سگهو ٿا؟
- لاگنگ درخواستون
- ڊيٽا ۽ رسائي جي وچولي تصديق
- ڪم ڪندڙ سلسلي جي شروعات
- هڪ اعتراض تائين رسائي جي رڪارڊنگ
فائدا ۽ نقصان
- + توهان سروس اعتراض تائين رسائي کي ڪنٽرول ڪري سگهو ٿا جڏهن توهان چاهيو ٿا
- + سروس اعتراض جي زندگي جي چڪر کي منظم ڪرڻ سان لاڳاپيل اضافي صلاحيتون
- + اهو ڪم ڪري ٿو بغير ڪنهن خدمت جي اعتراض جي
- + اهو ڪارڪردگي ۽ ڪوڊ سيڪيورٽي کي بهتر بڻائي ٿو.
- - اهو خطرو آهي ته ڪارڪردگي وڌيڪ خراب ٿيڻ جي ڪري وڌيڪ درخواستن جي ڪري
- - اهو طبقن جي جوڙجڪ کي وڌيڪ پيچيده بڻائي ٿو
عمل ۾ پراکسي نموني
اچو ته هڪ سسٽم لاڳو ڪريون جيڪو هارڊ ڊسڪ مان ٽرين ٽائيم ٽيبل پڙهي ٿو:public interface TrainTimetable {
String[] getTimetable();
String getTrainDepartureTime();
}
هتي اهو طبقو آهي جيڪو مکيه انٽرفيس کي لاڳو ڪري ٿو:
public class ElectricTrainTimetable implements TrainTimetable {
@Override
public String[] getTimetable() {
ArrayList<String> list = new ArrayList<>();
try {
Scanner scanner = new Scanner(new FileReader(new File("/tmp/electric_trains.csv")));
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
list.add(line);
}
} catch (IOException e) {
System.err.println("Error: " + e);
}
return list.toArray(new String[list.size()]);
}
@Override
public String getTrainDepartureTime(String trainId) {
String[] timetable = getTimetable();
for (int i = 0; i < timetable.length; i++) {
if (timetable[i].startsWith(trainId+";")) return timetable[i];
}
return "";
}
}
هر دفعي توهان ٽرين ٽائيم ٽيبل حاصل ڪريو، پروگرام ڊسڪ مان هڪ فائل پڙهي ٿو. پر اهو صرف اسان جي مشڪلاتن جي شروعات آهي. پوري فائل هر وقت پڙهي ويندي آهي جڏهن توهان هڪ ٽرين جي ٽائم ٽيبل حاصل ڪندا آهيو! اهو سٺو آهي ته اهڙو ڪوڊ صرف انهن مثالن ۾ موجود آهي جيڪو نه ڪرڻ گهرجي :) ڪلائنٽ ڪلاس:
public class TimetableDisplay {
private TrainTimetable trainTimetable = new ElectricTrainTimetable();
public void printTimetable() {
String[] timetable = trainTimetable.getTimetable();
String[] tmpArr;
System.out.println("Train\\tFrom\\tTo\\t\\tDeparture time\\tArrival time\\tTravel time");
for (int i = 0; i < timetable.length; i++) {
tmpArr = timetable[i].split(";");
System.out.printf("%s\t%s\t%s\t\t%s\t\t\t\t%s\t\t\t%s\n", tmpArr[0], tmpArr[1], tmpArr[2], tmpArr[3], tmpArr[4], tmpArr[5]);
}
}
}
مثال فائل:
9B-6854;London;Prague;13:43;21:15;07:32
BA-1404;Paris;Graz;14:25;21:25;07:00
9B-8710;Prague;Vienna;04:48;08:49;04:01;
9B-8122;Prague;Graz;04:48;08:49;04:01
اچو ته جانچ ڪريون:
public static void main(String[] args) {
TimetableDisplay timetableDisplay = new timetableDisplay();
timetableDisplay.printTimetable();
}
پيداوار:
Train From To Departure time Arrival time Travel time
9B-6854 London Prague 13:43 21:15 07:32
BA-1404 Paris Graz 14:25 21:25 07:00
9B-8710 Prague Vienna 04:48 08:49 04:01
9B-8122 Prague Graz 04:48 08:49 04:01
هاڻي اچو ته اسان جي نموني کي متعارف ڪرائڻ لاء گهربل قدمن ذريعي هلون:
-
ھڪڙو انٽرفيس بيان ڪريو جيڪو اصل اعتراض جي بدران پراکسي جي استعمال جي اجازت ڏئي ٿو. اسان جي مثال ۾، هي آهي
TrainTimetable
. -
پراکسي ڪلاس ٺاهيو. ان کي خدمت جي اعتراض جو حوالو هجڻ گهرجي (ان کي ڪلاس ۾ ٺاهيو يا تعمير ڪندڙ ڏانهن وڃو).
هتي اسان جي پراکسي ڪلاس آهي:
public class ElectricTrainTimetableProxy implements TrainTimetable { // Reference to the original object private TrainTimetable trainTimetable = new ElectricTrainTimetable(); private String[] timetableCache = null @Override public String[] getTimetable() { return trainTimetable.getTimetable(); } @Override public String getTrainDepartureTime(String trainId) { return trainTimetable.getTrainDepartureTime(trainId); } public void clearCache() { trainTimetable = null; } }
هن مرحلي تي، اسان صرف اصل اعتراض جي حوالي سان هڪ ڪلاس ٺاهي رهيا آهيون ۽ سڀني ڪالن کي ان ڏانهن اڳتي وڌائي رهيا آهيون.
-
اچو ته پراکسي ڪلاس جي منطق کي لاڳو ڪريو. بنيادي طور تي، ڪالون هميشه اصل اعتراض ڏانهن منتقل ڪيا ويا آهن.
public class ElectricTrainTimetableProxy implements TrainTimetable { // Reference to the original object private TrainTimetable trainTimetable = new ElectricTrainTimetable(); private String[] timetableCache = null @Override public String[] getTimetable() { if (timetableCache == null) { timetableCache = trainTimetable.getTimetable(); } return timetableCache; } @Override public String getTrainDepartureTime(String trainId) { if (timetableCache == null) { timetableCache = trainTimetable.getTimetable(); } for (int i = 0; i < timetableCache.length; i++) { if (timetableCache[i].startsWith(trainId+";")) return timetableCache[i]; } return ""; } public void clearCache() { trainTimetable = null; } }
چيڪ
getTimetable()
ڪري ٿو ته ڇا ٽائيم ٽيبل صف ميموري ۾ محفوظ ڪئي وئي آهي. جيڪڏهن نه، اهو ڊسڪ مان ڊيٽا لوڊ ڪرڻ جي درخواست موڪلي ٿو ۽ نتيجو بچائي ٿو. جيڪڏهن ٽائيم ٽيبل اڳ ۾ ئي درخواست ڪئي وئي آهي، اهو جلدي ميموري مان اعتراض واپس آڻيندو.ان جي سادي ڪارڪردگي جي مهرباني، getTrainDepartureTime() طريقي کي اصل شئي ڏانهن ريڊائريڪٽ ٿيڻ جي ضرورت نه هئي. اسان صرف ان جي ڪارڪردگي کي نئين طريقي سان نقل ڪيو.
ائين نه ڪر. جيڪڏهن توهان کي ڪوڊ نقل ڪرڻو آهي يا ڪجهه ساڳيو ڪم ڪرڻو پوندو، پوء ڪجهه غلط ٿي ويو، ۽ توهان کي ٻيهر مسئلي کي مختلف زاوي کان ڏسڻ جي ضرورت آهي. اسان جي سادي مثال ۾، اسان وٽ ٻيو ڪو اختيار نه هو. پر حقيقي منصوبن ۾، ڪوڊ گهڻو ڪري وڌيڪ صحيح لکيو ويندو.
-
ڪلائنٽ ڪوڊ ۾، اصل اعتراض جي بدران هڪ پراکسي اعتراض ٺاهيو:
public class TimetableDisplay { // Changed reference private TrainTimetable trainTimetable = new ElectricTrainTimetableProxy(); public void printTimetable() { String[] timetable = trainTimetable.getTimetable(); String[] tmpArr; System.out.println("Train\\tFrom\\tTo\\t\\tDeparture time\\tArrival time\\tTravel time"); for (int i = 0; i < timetable.length; i++) { tmpArr = timetable[i].split(";"); System.out.printf("%s\t%s\t%s\t\t%s\t\t\t\t%s\t\t\t%s\n", tmpArr[0], tmpArr[1], tmpArr[2], tmpArr[3], tmpArr[4], tmpArr[5]); } } }
چيڪ
Train From To Departure time Arrival time Travel time 9B-6854 London Prague 13:43 21:15 07:32 BA-1404 Paris Graz 14:25 21:25 07:00 9B-8710 Prague Vienna 04:48 08:49 04:01 9B-8122 Prague Graz 04:48 08:49 04:01
عظيم، اهو صحيح ڪم ڪري ٿو.
توھان ھڪڙي ڪارخاني جي اختيار تي پڻ غور ڪري سگھو ٿا جيڪو ھڪڙي اصل اعتراض ۽ ھڪڙو پراکسي اعتراض پيدا ڪري ٿو، خاص شرطن تي منحصر آھي.
GO TO FULL VERSION