Design patterns
अनुकूलक
खोज…
एडाप्टर पैटर्न (PHP)
वैज्ञानिक प्रयोग का एक वास्तविक विश्व उदाहरण है जहाँ विभिन्न प्रकार के ऊतक पर कुछ दिनचर्याएँ की जाती हैं। ऊतक या दिनचर्या को अलग-अलग प्राप्त करने के लिए कक्षा में डिफ़ॉल्ट रूप से दो कार्य शामिल हैं। बाद के संस्करण में हमने एक नए वर्ग का उपयोग करके इसे अनुकूलित किया है ताकि दोनों को मिल सके। इसका मतलब है कि हमने मूल कोड को संपादित नहीं किया है और इसलिए हमारे मौजूदा वर्ग (और कोई रिटायरिंग) को तोड़ने का कोई जोखिम नहीं है।
class Experiment {
private $routine;
private $tissue;
function __construct($routine_in, $tissue_in) {
$this->routine = $routine_in;
$this->tissue = $tissue_in;
}
function getRoutine() {
return $this->routine;
}
function getTissue() {
return $this->tissue;
}
}
class ExperimentAdapter {
private $experiment;
function __construct(Experiment $experiment_in) {
$this->experiment = $experiment_in;
}
function getRoutineAndTissue() {
return $this->experiment->getTissue().' ('. $this->experiment->getRoutine().')';
}
}
एडाप्टर (जावा)
मान लें कि आपके वर्तमान कोडबेस में, MyLogger
इंटरफ़ेस मौजूद है जैसे:
interface MyLogger {
void logMessage(String message);
void logException(Throwable exception);
}
आओ हम कहते हैं कि आपने इनमें से कुछ ठोस कार्यान्वयन बनाए हैं, जैसे कि MyFileLogger
और MyConsoleLogger
।
आपने तय किया है कि आप अपने एप्लिकेशन की ब्लूटूथ कनेक्टिविटी को नियंत्रित करने के लिए एक रूपरेखा का उपयोग करना चाहते हैं। इस ढांचे में निम्नलिखित कंस्ट्रक्टर के साथ एक BluetoothManager
मैनेजर है:
class BluetoothManager {
private FrameworkLogger logger;
public BluetoothManager(FrameworkLogger logger) {
this.logger = logger;
}
}
BluetoothManager
मैन एक लकड़हारा भी स्वीकार करता है, जो बहुत अच्छा है! हालांकि यह एक लकड़हारा की उम्मीद करता है, जिसमें इंटरफ़ेस को रूपरेखा द्वारा परिभाषित किया गया था और उन्होंने अपने अलग नाम रखने के बजाय विधि का उपयोग किया है।
interface FrameworkLogger {
void log(String message);
void log(Throwable exception);
}
आपके पास पहले से ही MyLogger
कार्यान्वयन का एक गुच्छा है जिसे आप पुन: उपयोग करना चाहते हैं, लेकिन वे FrameworkLogger
के इंटरफ़ेस में फिट नहीं होते हैं। यह वह जगह है जहाँ एडेप्टर डिजाइन-पैटर्न में आता है:
class FrameworkLoggerAdapter implements FrameworkLogger {
private MyLogger logger;
public FrameworkLoggerAdapter(MyLogger logger) {
this.logger = logger;
}
@Override
public void log(String message) {
this.logger.logMessage(message);
}
@Override
public void log(Throwable exception) {
this.logger.logException(exception);
}
}
एक एडेप्टर वर्ग को परिभाषित करके जो FrameworkLogger
MyLogger
इंटरफेस को लागू करता है और एक MyLogger
कार्यान्वयन को स्वीकार करता है कार्यक्षमता को विभिन्न इंटरफेस के बीच मैप किया जा सकता है। अब MyLogger
सभी कार्यान्वयनों के साथ BluetoothManager
का उपयोग करना संभव है:
FrameworkLogger fileLogger = new FrameworkLoggerAdapter(new MyFileLogger());
BluetoothManager manager = new BluetoothManager(fileLogger);
FrameworkLogger consoleLogger = new FrameworkLoggerAdapter(new MyConsoleLogger());
BluetoothManager manager2 = new BluetoothManager(consoleLogger);
जावा उदाहरण
एडप्टर पैटर्न का एक बड़ा मौजूदा उदाहरण SWT माउसलिस्टनर और माउस एडेप्टर कक्षाओं में पाया जा सकता है।
माउसलिस्ट इंटरफ़ेस निम्नानुसार दिखता है:
public interface MouseListener extends SWTEventListener {
public void mouseDoubleClick(MouseEvent e);
public void mouseDown(MouseEvent e);
public void mouseUp(MouseEvent e);
}
अब एक ऐसे परिदृश्य की कल्पना करें जहां आप UI बना रहे हैं और इन श्रोताओं को जोड़ रहे हैं, लेकिन अधिकांश समय आप किसी चीज़ के अलावा किसी और चीज़ की परवाह नहीं करते हैं जब कोई सिंगल क्लिक (माउसअप) करता है। आप लगातार खाली कार्यान्वयन नहीं बनाना चाहेंगे:
obj.addMouseListener(new MouseListener() {
@Override
public void mouseDoubleClick(MouseEvent e) {
}
@Override
public void mouseDown(MouseEvent e) {
}
@Override
public void mouseUp(MouseEvent e) {
// Do the things
}
});
इसके बजाय, हम माउस एडेप्टर का उपयोग कर सकते हैं:
public abstract class MouseAdapter implements MouseListener {
public void mouseDoubleClick(MouseEvent e) { }
public void mouseDown(MouseEvent e) { }
public void mouseUp(MouseEvent e) { }
}
खाली, डिफ़ॉल्ट कार्यान्वयन प्रदान करके, हम केवल उन्हीं तरीकों को ओवरराइड करने के लिए स्वतंत्र हैं, जिन्हें हम एडॉप्टर से देखभाल करते हैं। उपरोक्त उदाहरण से:
obj.addMouseListener(new MouseAdapter() {
@Override
public void mouseUp(MouseEvent e) {
// Do the things
}
});
एडाप्टर (UML और उदाहरण स्थिति)
एडेप्टर पैटर्न और उस तरह की स्थिति का उपयोग करने के लिए जब इसे अधिक कल्पनाशील रूप से लागू किया जा सकता है, एक छोटा, सरल और बहुत ही ठोस उदाहरण यहां दिया गया है। यहां कोई कोड नहीं होगा, बस यूएमएल और उदाहरण की स्थिति और इसकी समस्या का विवरण होगा। माना जाता है कि, UML सामग्री जावा की तरह लिखी जाती है। (ठीक है, संकेत पाठ ने कहा "अच्छे उदाहरण ज्यादातर कोड हैं", मुझे लगता है कि डिजाइन पैटर्न एक अलग तरीके से पेश किए जाने के लिए पर्याप्त सार हैं।)
सामान्य तौर पर, एडेप्टर पैटर्न एक ऐसी स्थिति के लिए पर्याप्त समाधान है जब आपके पास असंगत इंटरफेस होते हैं और उनमें से कोई भी सीधे नहीं लिखा जा सकता है।
कल्पना कीजिए कि आप एक अच्छी छोटी पिज्जा डिलीवरी सेवा चला रहे हैं। ग्राहक आपकी वेबसाइट पर ऑनलाइन ऑर्डर कर सकते हैं और आपके Pizza
का प्रतिनिधित्व करने और बिल, टैक्स रिपोर्ट और अन्य चीजों की गणना करने के लिए एक क्लास Pizza
का उपयोग करने की छोटी प्रणाली है। आपके पिज्जा की कीमत एक पूर्णांक के रूप में दी जाती है, जो प्रतिशत में मूल्य (आपकी पसंद की मुद्रा) का प्रतिनिधित्व करती है।
आपकी डिलीवरी सेवा बढ़िया काम कर रही है, लेकिन कुछ बिंदु पर आप ग्राहकों की बढ़ती संख्या को अपने दम पर नहीं संभाल सकते हैं, लेकिन आप अभी भी विस्तार करना चाहते हैं। आप अपने पिज्जा को एक बड़ी ऑनलाइन मेटा डिलीवरी सेवा के मेनू में जोड़ने का निर्णय लेते हैं। वे बहुत सारे अलग-अलग भोजन पेश करते हैं - केवल पिज्जा ही नहीं - इसलिए उनका सिस्टम अमूर्तता का अधिक उपयोग करता है और इसमें एक इंटरफेस IMeal
जो भोजन का प्रतिनिधित्व करता है और साथ में एक क्लास MoneyAmount
पैसे का प्रतिनिधित्व करता है।
MoneyAmount
में इनपुट के रूप में दो पूर्णांक होते हैं, एक अल्पविराम से पहले राशि (या कुछ यादृच्छिक मुद्रा) के लिए, और एक अल्पविराम के बाद 0 से 99 तक की राशि के लिए;
इस तथ्य के कारण कि आपके Pizza
की कीमत एक एकल पूर्णांक है जो प्रतिशत की राशि (> 99) के रूप में कुल मूल्य का प्रतिनिधित्व करती है, यह IMeal
के साथ संगत नहीं है। यह वह बिंदु है जहां एडेप्टर पैटर्न खेल में आता है: यदि यह आपके स्वयं के सिस्टम को बदलने या एक नया बनाने में बहुत अधिक प्रयास करेगा और आपको एक असंगत इंटरफ़ेस को लागू करना होगा, तो आप एडेप्टर पेटर्न को लागू कर सकते हैं।
पैटर्न लागू करने के दो तरीके हैं: क्लास एडॉप्टर और ऑब्जेक्ट एडेप्टर।
दोनों में आम बात है कि एक एडेप्टर ( PizzaAdapter
एडेप्टर) नए इंटरफ़ेस और एडापेटी (इस उदाहरण में Pizza
) के बीच किसी प्रकार के अनुवादक के रूप में काम करता है। एडॉप्टर नए इंटरफ़ेस ( IMeal
) को लागू करता है और फिर या तो Pizza
से विरासत में मिलता है और अपने स्वयं के मूल्य को एक पूर्णांक से दो (क्लास एडाप्टर) में परिवर्तित करता है।
या विशेषता के रूप में प्रकार Pizza
की एक वस्तु है और उस (वस्तु अनुकूलक) के मूल्यों को धर्मान्तरित करता है।
एडेप्टर पैटर्न को लागू करके, आप असंगत इंटरफेस के बीच "अनुवाद" करेंगे।