"हैलो दोस्त!"

"हाय, बिलाबो!"

"हमारे पास अभी भी कुछ समय बचा है, इसलिए मैं आपको तीन और पैटर्न के बारे में बताऊँगा।"

"तीन और? कुल कितने हैं?"

"वर्तमान में दर्जनों लोकप्रिय पैटर्न हैं, लेकिन «सफल समाधान» की संख्या असीमित है।"

"अच्छा। तो मुझे कई दर्जन पैटर्न सीखने होंगे?"

"जब तक आपके पास वास्तविक प्रोग्रामिंग अनुभव नहीं होगा, तब तक वे आपको बहुत कुछ नहीं देंगे।"

"बेहतर होगा कि आप थोड़ा और अनुभव प्राप्त करें, और फिर, एक वर्ष में, इस विषय पर लौटें और उन्हें और गहराई से समझने की कोशिश करें। कम से कम दो दर्जन सबसे लोकप्रिय डिज़ाइन पैटर्न।"

"किसी और के अनुभव का उपयोग नहीं करना और इसके बजाय 110 वीं बार कुछ आविष्कार करना पाप है।"

"मैं सहमत हूं।"

"तो चलिए शुरू करते हैं।"

अनुकूलक (या आवरण) पैटर्न

पैटर्न: एडेप्टर, प्रॉक्सी, ब्रिज - 1

"कल्पना करें कि आप चीन आते हैं और पाते हैं कि बिजली के आउटलेट एक अलग मानक का पालन करते हैं। छेद गोल नहीं हैं, लेकिन सपाट हैं। इस मामले में, आपको एक एडेप्टर की आवश्यकता होगी।"

"ऐसा ही कुछ प्रोग्रामिंग में भी हो सकता है। कक्षाएं समान लेकिन अलग-अलग इंटरफेस पर काम करती हैं। इसलिए हमें उनके बीच एक एडेप्टर बनाने की जरूरत है।"

"यह कैसा दिखता है:"

उदाहरण
interface Time
{
 int getSeconds();
 int getMinutes();
 int getHours();
}

interface TotalTime
{
 int getTotalSeconds();
}

"मान लें कि हमारे पास दो इंटरफेस हैं: समय  और  कुल समय ।"

"समय इंटरफ़ेस आपको getSeconds (),  getMinutes () और  getHours () विधियों का उपयोग करके वर्तमान समय प्राप्त करने देता है ।"

" टोटलटाइम इंटरफ़ेस आपको आधी रात से लेकर वर्तमान क्षण तक के सेकंड की संख्या प्राप्त करने देता है।"

"अगर हमारे पास टोटलटाइम ऑब्जेक्ट है तो हमें क्या करना चाहिए , लेकिन हमें टाइम ऑब्जेक्ट या इसके विपरीत चाहिए?"

"हम इसके लिए एडेप्टर कक्षाएं लिख सकते हैं। उदाहरण के लिए:"

उदाहरण
 class TotalTimeAdapter implements Time
{
 private TotalTime totalTime;
 public TotalTimeAdapter(TotalTime totalTime)
 {
  this.totalTime = totalTime;
 }

 int getSeconds()
 {
  return totalTime.getTotalSeconds() % 60; // seconds
 }

 int getMinutes()
 {
  return totalTime.getTotalSeconds() / 60; // minutes
 }

 int getHours()
 {
  return totalTime.getTotalSeconds() / (60 * 60); // hours
 }
}
 
प्रयोग
TotalTime totalTime = TimeManager.getCurrentTime();
Time time = new TotalTimeAdapter(totalTime);
System.out.println(time.getHours() + " : " + time.getMinutes () + " : " +time.getSeconds());

"और दूसरी दिशा में एक अनुकूलक:"

उदाहरण
class TimeAdapter implements TotalTime
{
 private Time time;
 public TimeAdapter(Time time)
 {
  this.time = time;
 }

 int getTotalSeconds()
 {
  return time.getHours() * 60 * 60 + time.getMinutes() * 60 + time.getSeconds();
 }
}
प्रयोग
Time time = new Time();
TotalTime totalTime = new TimeAdapter(time);
System.out.println(time.getTotalSeconds());

"आह। मुझे यह पसंद है। लेकिन क्या कोई उदाहरण हैं?"

"बेशक! एक उदाहरण के रूप में, InputStreamReader एक क्लासिक एडेप्टर है। यह एक InputStream को एक रीडर में परिवर्तित करता है।"

"कभी-कभी इस पैटर्न को एक आवरण भी कहा जाता है, क्योंकि नया वर्ग किसी अन्य वस्तु को लपेटता है।"

"आप यहां कुछ और दिलचस्प बातें पढ़ सकते हैं ।"

प्रॉक्सी पैटर्न

"प्रॉक्सी पैटर्न कुछ हद तक रैपर पैटर्न के समान है। लेकिन इसका उद्देश्य इंटरफेस को परिवर्तित करना नहीं है, बल्कि प्रॉक्सी क्लास के अंदर संग्रहीत मूल वस्तु तक पहुंच को नियंत्रित करना है। इसके अलावा, मूल वर्ग और प्रॉक्सी दोनों में आमतौर पर एक ही इंटरफ़ेस होता है, जो मूल वर्ग के ऑब्जेक्ट को प्रॉक्सी ऑब्जेक्ट से बदलना आसान बनाता है।"

"उदाहरण के लिए:"

वास्तविक वर्ग का इंटरफ़ेस
interface Bank
{
 public void setUserMoney(User user, double money);
 public int getUserMoney(User user);
}
मूल वर्ग का कार्यान्वयन
class CitiBank implements Bank
{
 public void setUserMoney(User user, double money)
 {
  UserDAO.updateMoney(user, money);
 }

 public int getUserMoney(User user)
 {
  return UserDAO.getMoney(user);
 }
}
प्रॉक्सी वर्ग का कार्यान्वयन
class BankSecurityProxy implements Bank
{
 private Bank bank;
 public BankSecurityProxy(Bank bank)
 {
  this.bank = bank;
 }
 public void setUserMoney(User user, double money)
 {
  if (!SecurityManager.authorize(user, BankAccounts.Manager))
  throw new SecurityException("User can’t change money value");

  bank.setUserMoney(user, money);
 }

 public int getUserMoney(User user)
 {
  if (!SecurityManager.authorize(user, BankAccounts.Manager))
  throw new SecurityException("User can’t get money value");

  return bank.getUserMoney(user);
 }
}

"उपरोक्त उदाहरण में, हमने बैंक इंटरफ़ेस और सिटीबैंक वर्ग, इस इंटरफ़ेस के कार्यान्वयन का वर्णन किया है।"

"इंटरफ़ेस आपको उपयोगकर्ता के खाते की शेष राशि प्राप्त करने या बदलने देता है।"

और फिर हमने BankSecurityProxy बनाया , जो बैंक इंटरफ़ेस को भी लागू करता है और एक अलग बैंक इंटरफ़ेस के संदर्भ को संग्रहीत करता है। इस वर्ग की विधियाँ जाँचती हैं कि उपयोगकर्ता खाता स्वामी है या बैंक प्रबंधक। यदि ऐसा नहीं है, तो सुरक्षा अपवाद फेंक दिया जाता है।"

"यहां बताया गया है कि यह व्यवहार में कैसे काम करता है:"

सुरक्षा जांच के बिना कोड :
User user = AuthManager.authorize(login, password);
Bank bank = BankFactory.createUserBank(user);
bank.setUserMoney(user, 1000000);
सुरक्षा जांच के साथ कोड :
User user = AuthManager.authorize(login, password);
Bank bank = BankFactory.createUserBank(user);
bank = new BankSecurityProxy(bank);
bank.setUserMoney(user, 1000000);

"पहले उदाहरण में, हम एक बैंक ऑब्जेक्ट बनाते हैं और इसके सेटयूजरमनी मेथड को कॉल करते हैं।

"दूसरे उदाहरण में, हम मूल बैंक ऑब्जेक्ट को BankSecurityProxy ऑब्जेक्ट में लपेटते हैं। उनके पास एक ही इंटरफ़ेस है, इसलिए बाद का कोड उसी तरह काम करना जारी रखता है जैसा उसने किया था। लेकिन अब हर बार एक विधि कॉल करने पर एक सुरक्षा जांच की जाएगी।"

"ठंडा!"

"हां। आपके पास ऐसे कई प्रॉक्सी हो सकते हैं। उदाहरण के लिए, आप एक और प्रॉक्सी जोड़ सकते हैं जो यह जांचता है कि खाते की शेष राशि बहुत बड़ी है या नहीं। बैंक प्रबंधक अपने खाते में बहुत पैसा लगाने का फैसला कर सकता है और धन के साथ क्यूबा से फरार हो सकता है।" "

"क्या अधिक है... वस्तुओं की इन सभी श्रृंखलाओं के निर्माण को BankFactory वर्ग में रखा जा सकता है, जहाँ आप अपनी आवश्यकता के अनुसार सक्षम/अक्षम कर सकते हैं।"

" बफर्डरीडर एक समान सिद्धांत का उपयोग कर काम करता है। यह एक रीडर है , लेकिन यह अतिरिक्त काम करता है।"

"यह दृष्टिकोण आपको विभिन्न «टुकड़ों» से आवश्यक कार्यक्षमता के साथ एक वस्तु «इकट्ठा» करने देता है।

"ओह, मैं लगभग भूल ही गया था। मैंने अभी आपको जो दिखाया है, उससे कहीं अधिक व्यापक रूप से प्रॉक्सी का उपयोग किया जाता है। आप यहां अन्य उपयोगों के बारे में पढ़ सकते हैं। "

ब्रिज पैटर्न

पैटर्न: एडेप्टर, प्रॉक्सी, ब्रिज - 2

"कभी-कभी जब कोई प्रोग्राम चलता है तो किसी वस्तु की कार्यक्षमता को महत्वपूर्ण रूप से बदलना आवश्यक होता है। उदाहरण के लिए, मान लीजिए कि आपके पास एक गधे के चरित्र वाला एक खेल है जिसे बाद में एक दाना द्वारा ड्रैगन में बदल दिया गया। ड्रैगन का व्यवहार और गुण पूरी तरह से अलग है, लेकिन यह है वही वस्तु!"

"क्या हम सिर्फ एक नई वस्तु नहीं बना सकते हैं और इसके साथ किया जा सकता है?"

"हमेशा नहीं। मान लीजिए कि आपका गधा पात्रों के एक समूह के साथ दोस्त है, या शायद यह कई मंत्रों के प्रभाव में था, या यह कुछ खोजों में शामिल था। दूसरे शब्दों में, वस्तु पहले से ही कई जगहों पर उपयोग में हो सकती है - और कई अन्य वस्तुओं से जुड़ा हुआ है। इसलिए इस मामले में, यह केवल एक नई वस्तु बनाने का विकल्प नहीं है।"

"अच्छा, फिर क्या किया जा सकता है?"

"ब्रिज पैटर्न सबसे सफल समाधानों में से एक है।"

"यह पैटर्न एक वस्तु को दो वस्तुओं में विभाजित करने पर जोर देता है: एक «इंटरफ़ेस ऑब्जेक्ट» और एक «कार्यान्वयन वस्तु»।

"इंटरफ़ेस और इसे लागू करने वाले वर्ग के बीच क्या अंतर है?"

"एक इंटरफ़ेस और एक वर्ग के साथ, हम एक वस्तु के साथ समाप्त होते हैं। लेकिन यहाँ - हमारे पास दो हैं। इस उदाहरण को देखें:"

उदाहरण
class User
{
 private UserImpl realUser;

 public User(UserImpl impl)
 {
  realUser = impl;
 }

 public void run() //Run
 {
  realUser.run();
 }

 public void fly() //Fly
 {
  realUser.fly();
 }
}

class UserImpl
{
 public void run()
 {
 }

 public void fly()
 {
 }
}

"और फिर आप UserImpl के कई उपवर्गों की घोषणा कर सकते हैं, उदाहरण के लिए UserDonkey (गधा) और UserDragon (ड्रैगन)।"

"फिर भी, मैं वास्तव में नहीं समझता कि यह कैसे काम करेगा।"

"ठीक है, ऐसा कुछ:"

उदाहरण
class User
{
 private UserImpl realUser;

 public User(UserImpl impl)
 {
  realUser = impl;
 }

 public void transformToDonkey()
 {
  realUser = new UserDonkeyImpl();
 }

 public void transformToDragon()
 {
  realUser = new UserDragonImpl();
 }
}
यह काम किस प्रकार करता है
User user = new User(new UserDonkey()); // Internally, we're a donkey
user.transformToDragon(); // Now we're a dragon internally

"तो यह एक प्रॉक्सी जैसा कुछ है।"

"हाँ, लेकिन एक प्रॉक्सी में मुख्य वस्तु को कहीं अलग से संग्रहीत किया जा सकता है, और कोड इसके बजाय प्रॉक्सी के साथ काम करता है। यहां हम कह रहे हैं कि हर कोई मुख्य वस्तु के साथ काम करता है, लेकिन इसके हिस्से आंतरिक रूप से बदलते हैं।"

"आह। धन्यवाद। क्या आप मुझे इसके बारे में और पढ़ने के लिए एक लिंक देंगे?"

"बेशक, अमीगो, मेरे दोस्त। ये लो: ब्रिज पैटर्न ।"