ہائے! آج ہم ایک اہم نئے موضوع پر بات کریں گے: ڈیزائن پیٹرن ۔ یہ پیٹرن کیا ہیں؟ مجھے لگتا ہے کہ آپ کو " پہیہ کو دوبارہ ایجاد نہ کریں " کا اظہار معلوم ہونا چاہئے ۔ پروگرامنگ میں، بہت سے دوسرے شعبوں کی طرح، عام حالات کی ایک بڑی تعداد ہے۔ جیسا کہ سافٹ ویئر کی ترقی تیار ہوئی ہے، ان میں سے ہر ایک کے لیے تیار حل تیار کیے گئے ہیں۔ ان حلوں کو ڈیزائن پیٹرن کہا جاتا ہے۔ کنونشن کے مطابق، ایک پیٹرن کچھ حل ہے جو اس طرح تیار کیا جاتا ہے: "اگر آپ کو اپنے پروگرام میں X کرنے کی ضرورت ہے، تو یہ ایسا کرنے کا بہترین طریقہ ہے"۔ بہت سارے نمونے ہیں۔ بہترین کتاب "Head First Design Patterns"، جس سے آپ کو ضرور واقف ہونا چاہیے، ان کے لیے وقف ہے۔
مختصر الفاظ میں، ایک پیٹرن ایک عام مسئلہ اور متعلقہ حل پر مشتمل ہوتا ہے جسے ایک قسم کا معیار سمجھا جا سکتا ہے۔ آج کے سبق میں، ہم ان نمونوں میں سے ایک سے ملیں گے: اڈاپٹر۔ اس کا نام یہ سب کہتا ہے، اور آپ کو حقیقی زندگی میں کئی بار اڈیپٹرز کا سامنا کرنا پڑا ہے۔ کچھ سب سے عام اڈاپٹر کارڈ ریڈرز ہیں جو بہت سے کمپیوٹرز اور لیپ ٹاپس کے پاس ہوتے ہیں۔
فرض کریں کہ ہمارے پاس کسی قسم کا میموری کارڈ ہے۔ تو کیا مسئلہ ہے؟ یہ کمپیوٹر کے ساتھ بات چیت کرنے کا طریقہ نہیں جانتا ہے۔ وہ مشترکہ انٹرفیس کا اشتراک نہیں کرتے ہیں۔ کمپیوٹر میں USB پورٹ ہے، لیکن ہم اس میں میموری کارڈ نہیں ڈال سکتے۔ کارڈ کو کمپیوٹر میں نہیں لگایا جا سکتا، اس لیے ہم اپنی تصاویر، ویڈیوز اور دیگر ڈیٹا کو محفوظ نہیں کر سکتے۔ کارڈ ریڈر ایک اڈاپٹر ہے جو اس مسئلے کو حل کرتا ہے۔ سب کے بعد، یہ ایک USB کیبل ہے! کارڈ کے برعکس، کارڈ ریڈر کو کمپیوٹر میں پلگ کیا جا سکتا ہے۔ وہ کمپیوٹر کے ساتھ ایک مشترکہ انٹرفیس کا اشتراک کرتے ہیں: USB۔ آئیے دیکھتے ہیں کہ یہ عملی طور پر کیسا لگتا ہے:
طریقوں کا ایک سیٹ بالکل وہی ہے جو انٹرفیس ہے۔ جیسا کہ آپ دیکھ سکتے ہیں، اس کلاس کا ایک
تاہم،
اور اگرچہ ہماری


public interface USB {
void connectWithUsbCable();
}
یہ ہمارا USB انٹرفیس ہے جس میں USB کے ذریعے جڑنے کا صرف ایک طریقہ ہے۔
public class MemoryCard {
public void insert() {
System.out.println("Memory card successfully inserted!");
}
public void copyData() {
System.out.println("The data has been copied to the computer!");
}
}
یہ ہماری کلاس ہے جو میموری کارڈ کی نمائندگی کرتی ہے۔ اس کے پاس پہلے سے ہی 2 طریقے ہیں جن کی ہمیں ضرورت ہے، لیکن یہاں مسئلہ ہے: یہ USB انٹرفیس کو نافذ نہیں کرتا ہے۔ کارڈ کو USB پورٹ میں داخل نہیں کیا جا سکتا۔
public class CardReader implements USB {
private MemoryCard memoryCard;
public CardReader(MemoryCard memoryCard) {
this.memoryCard = memoryCard;
}
@Override
public void connectWithUsbCable() {
this.memoryCard.insert();
this.memoryCard.copyData();
}
}
اور یہاں ہمارا اڈاپٹر ہے! کلاس کیا CardReader
کرتی ہے اور اسے بالکل اڈاپٹر کیا بناتا ہے؟ یہ سب آسان ہے۔ جس کلاس کو اپنایا جا رہا ہے (میموری کارڈ) اڈاپٹر کے فیلڈز میں سے ایک بن جاتا ہے۔ یہ سمجھ میں آتا ہے۔ جب ہم حقیقی زندگی میں کارڈ ریڈر کے اندر میموری کارڈ رکھتے ہیں تو یہ بھی اس کا حصہ بن جاتا ہے۔ میموری کارڈ کے برعکس، اڈاپٹر کمپیوٹر کے ساتھ ایک انٹرفیس کا اشتراک کرتا ہے۔ اس میں یو ایس بی کیبل ہے یعنی اسے یو ایس بی کے ذریعے دیگر ڈیوائسز سے کنیکٹ کیا جا سکتا ہے۔ اسی لیے ہماری کارڈ ریڈر کلاس USB انٹرفیس کو نافذ کرتی ہے۔ لیکن اس طریقہ کار کے اندر بالکل کیا ہوتا ہے؟ بالکل وہی جو ہمیں ہونے کی ضرورت ہے! اڈاپٹر ہمارے میموری کارڈ کو کام سونپتا ہے۔ درحقیقت، اڈاپٹر خود کچھ نہیں کرتا ہے۔ کارڈ ریڈر کے پاس کوئی آزاد فعالیت نہیں ہے۔ اس کا کام صرف کمپیوٹر اور میموری کارڈ کو جوڑنا ہے تاکہ کارڈ کو اپنا کام کرنے کی اجازت دی جا سکے — فائلوں کو کاپی کرنا! connectWithUsbCable()
ہمارا اڈاپٹر میموری کارڈ کی "ضروریات" کو پورا کرنے کے لیے اپنا انٹرفیس (طریقہ) فراہم کر کے اسے قابل بناتا ہے ۔ آئیے کچھ کلائنٹ پروگرام بنائیں جو کسی ایسے شخص کی تقلید کرے جو میموری کارڈ سے ڈیٹا کاپی کرنا چاہتا ہے:
public class Main {
public static void main(String[] args) {
USB cardReader = new CardReader(new MemoryCard());
cardReader.connectWithUsbCable();
}
}
تو ہمیں کیا ملا؟ کنسول آؤٹ پٹ:
Memory card successfully inserted!
The data has been copied to the computer!
بہترین ہم نے اپنا مقصد حاصل کر لیا! اڈاپٹر پیٹرن کے بارے میں معلومات کے ساتھ ویڈیو کا لنک یہ ہے:
ریڈر اور رائٹر خلاصہ کلاسز
اب ہم اپنی پسندیدہ سرگرمی پر واپس جائیں گے: ان پٹ اور آؤٹ پٹ کے ساتھ کام کرنے کے لیے کچھ نئی کلاسوں کے بارے میں سیکھنا :) مجھے حیرت ہے کہ ہم نے پہلے ہی کتنے کے بارے میں سیکھا ہے۔ آج ہمReader
اور Writer
کلاسز کے بارے میں بات کریں گے۔ خاص طور پر وہ کلاسز کیوں؟ کیونکہ وہ اڈیپٹرز کے بارے میں ہمارے پچھلے حصے سے متعلق ہیں۔ آئیے ان کا مزید تفصیل سے جائزہ لیں۔ ہم کے ساتھ شروع کریں گے Reader
. Reader
ایک تجریدی کلاس ہے، لہذا ہم واضح طور پر اشیاء نہیں بنا سکیں گے۔ لیکن آپ اصل میں اس سے پہلے ہی واقف ہیں! BufferedReader
سب کے بعد، آپ کو اور کلاسوں سے اچھی طرح واقف ہیں InputStreamReader
، جو اس کی اولاد ہیں :)
public class BufferedReader extends Reader {
…
}
public class InputStreamReader extends Reader {
…
}
کلاس InputStreamReader
ایک کلاسک اڈاپٹر ہے۔ جیسا کہ آپ کو شاید یاد ہے، ہم کسی InputStream
چیز کو اس کے کنسٹرکٹر تک پہنچا سکتے ہیں۔ ایسا کرنے کے لیے، ہم عام طور پر System.in
متغیر کا استعمال کرتے ہیں:
public static void main(String[] args) {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
لیکن کیا InputStreamReader
کرتا ہے؟ ہر اڈاپٹر کی طرح، یہ ایک انٹرفیس کو دوسرے میں تبدیل کرتا ہے۔ اس صورت میں، InputStream
انٹرفیس کو Reader
انٹرفیس. ابتدائی طور پر، ہمارے پاس InputStream
کلاس ہے. یہ اچھی طرح سے کام کرتا ہے، لیکن آپ اسے صرف انفرادی بائٹس کو پڑھنے کے لیے استعمال کر سکتے ہیں۔ اس کے علاوہ، ہمارے پاس ایک Reader
خلاصہ کلاس ہے۔ اس میں کچھ بہت مفید فعالیت ہے — یہ حروف کو پڑھنا جانتا ہے! ہمیں یقیناً اس صلاحیت کی ضرورت ہے۔ لیکن یہاں ہمیں کلاسک مسئلہ کا سامنا ہے جو عام طور پر اڈیپٹرز کے ذریعہ حل کیا جاتا ہے - غیر مطابقت پذیر انٹرفیس۔ اس کا کیا مطلب ہے؟ آئیے اوریکل دستاویزات پر ایک نظر ڈالیں۔ کلاس کے طریقے یہ ہیں InputStream
۔ 
read()
طریقہ ہے (حقیقت میں چند قسمیں)، لیکن یہ صرف بائٹس پڑھ سکتی ہے: یا تو انفرادی بائٹس، یا بفر کا استعمال کرتے ہوئے کئی بائٹس۔ لیکن یہ آپشن ہمارے مطابق نہیں ہے — ہم حروف کو پڑھنا چاہتے ہیں۔ ہمیں اس فعالیت کی ضرورت ہے جو خلاصہ کلاس میں پہلے سے نافذReader
ہے ۔ ہم اسے دستاویزات میں بھی دیکھ سکتے ہیں۔ 
InputStream
اور Reader
انٹرفیس مطابقت نہیں رکھتے ہیں! جیسا کہ آپ دیکھ سکتے ہیں، طریقہ کار کے ہر نفاذ میں read()
مختلف پیرامیٹرز اور واپسی کی قدریں ہوتی ہیں۔ اور یہ وہ جگہ ہے جہاں ہمیں ضرورت ہے InputStreamReader
! یہ ہماری کلاسوں کے درمیان ایک اڈاپٹر کے طور پر کام کرے گا۔ جیسا کہ کارڈ ریڈر کے ساتھ مثال کے طور پر، جس پر ہم نے اوپر غور کیا، ہم کلاس کو اڈاپٹر کلاس کے "اندر" ڈھالنے کی مثال دیتے ہیں، یعنی ہم ایک کو اس کے کنسٹرکٹر کو دیتے ہیں۔ پچھلی مثال میں، ہم MemoryCard
اندر ایک چیز ڈالتے ہیں CardReader
۔ اب ہم ایک InputStream
اعتراض InputStreamReader
کنسٹرکٹر کو دے رہے ہیں! ہم اپنے مانوس System.in
متغیر کو بطور استعمال کرتے ہیں InputStream
:
public static void main(String[] args) {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
اور درحقیقت، کے لیے دستاویزات کو دیکھتے ہوئے InputStreamReader
، ہم دیکھ سکتے ہیں کہ موافقت کامیاب ہوئی :) اب ہمارے پاس اپنے اختیار میں حروف کو پڑھنے کے طریقے ہیں۔ 
System.in
آبجیکٹ (کی بورڈ کے ساتھ جڑی ہوئی ندی) نے ابتدا میں اس کی اجازت نہیں دی، لیکن زبان کے تخلیق کاروں نے اڈاپٹر پیٹرن کو نافذ کرکے اس مسئلے کو حل کیا۔ تجریدی Reader
کلاس، زیادہ تر I/O کلاسوں کی طرح، ایک جڑواں بھائی ہے — Writer
۔ اس کا اتنا ہی بڑا فائدہ ہے Reader
- یہ کرداروں کے ساتھ کام کرنے کے لیے ایک آسان انٹرفیس فراہم کرتا ہے۔ آؤٹ پٹ اسٹریمز کے ساتھ، مسئلہ اور اس کا حل ان پٹ اسٹریمز کی طرح ہی نظر آتا ہے۔ ایک OutputStream
کلاس ہے جو صرف بائٹس لکھ سکتی ہے، ایک Writer
خلاصہ کلاس ہے جو حروف کے ساتھ کام کرنا جانتی ہے، اور دو متضاد انٹرفیس ہیں۔ یہ مسئلہ ایک بار پھر اڈاپٹر پیٹرن کی طرف سے حل کیا جاتا ہے. ہم کلاس اور کلاس OutputStreamWriter
کے دو انٹرفیس کو آسانی سے ایک دوسرے سے ڈھالنے کے لیے استعمال کرتے ہیں۔ کنسٹرکٹر کو بائٹ سٹریم دینے کے بعد ، ہم بائٹس کے بجائے حروف لکھنے کے لیے an کا استعمال کر سکتے ہیں! Writer
OutputStream
OutputStream
OutputStreamWriter
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
OutputStreamWriter streamWriter = new OutputStreamWriter(new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt"));
streamWriter.write(32144);
streamWriter.close();
}
}
ہم نے بائٹس کے ساتھ کام کرنے کی ضرورت کو ختم کرتے ہوئے اپنی فائل میں کوڈ 32144 (綐) کے ساتھ کیریکٹر لکھا :) آج کے لیے بس۔ اگلے اسباق میں ملتے ہیں! :)
GO TO FULL VERSION