हमने पहले ही एक सिंगलटन ऑब्जेक्ट के उपयोग की समीक्षा कर ली है, लेकिन आप अभी तक यह महसूस नहीं कर सकते हैं कि यह रणनीति एक डिज़ाइन पैटर्न है, और उस पर सबसे अधिक उपयोग की जाने वाली में से एक है।

वास्तव में, इनमें से बहुत सारे पैटर्न हैं, और उन्हें उनके विशिष्ट उद्देश्य के अनुसार वर्गीकृत किया जा सकता है।

पैटर्न वर्गीकरण

पैटर्न प्रकार आवेदन
क्रिएशनल एक प्रकार जो वस्तु निर्माण समस्या को हल करता है
संरचनात्मक पैटर्न जो हमें अपने आर्किटेक्चर में एक सही और एक्स्टेंसिबल क्लास पदानुक्रम बनाने देते हैं
व्यवहार पैटर्न का यह समूह किसी प्रोग्राम में वस्तुओं के बीच सुरक्षित और सुविधाजनक संपर्क की सुविधा प्रदान करता है।

आमतौर पर, एक पैटर्न की विशेषता उस समस्या से होती है जिसे वह हल करता है। आइए जावा के साथ काम करते समय सबसे अधिक बार सामना किए जाने वाले कुछ पैटर्न पर एक नज़र डालते हैं:

नमूना उद्देश्य
एकाकी वस्तु हम पहले से ही इस पैटर्न से परिचित हैं - हम इसका उपयोग उस वर्ग को बनाने और एक्सेस करने के लिए करते हैं जिसमें एक से अधिक उदाहरण नहीं हो सकते।
इटरेटर इससे हम भी परिचित हैं। हम जानते हैं कि यह पैटर्न हमें अपने आंतरिक प्रतिनिधित्व को प्रकट किए बिना किसी संग्रह वस्तु पर पुनरावृति करने देता है। इसका उपयोग संग्रह के साथ किया जाता है।
अनुकूलक यह पैटर्न असंगत वस्तुओं को जोड़ता है ताकि वे एक साथ काम कर सकें। मुझे लगता है कि एडेप्टर पैटर्न का नाम आपको यह कल्पना करने में मदद करता है कि यह वास्तव में क्या करता है। यहां वास्तविक जीवन से एक सरल उदाहरण दिया गया है: वॉल आउटलेट के लिए एक यूएसबी एडॉप्टर।
टेम्पलेट विधि

एक व्यवहार प्रोग्रामिंग पैटर्न जो एकीकरण समस्या को हल करता है और आपको एल्गोरिथम की संरचना को बदले बिना एल्गोरिथम चरणों को बदलने की अनुमति देता है।

कल्पना कीजिए कि हमारे पास असेंबली चरणों के अनुक्रम के रूप में कार असेंबली एल्गोरिदम है:

चेसिस -> बॉडी -> इंजन -> केबिन इंटीरियर

यदि हम एक प्रबलित फ्रेम, एक अधिक शक्तिशाली इंजन, या अतिरिक्त प्रकाश व्यवस्था के साथ एक इंटीरियर में रखते हैं, तो हमें एल्गोरिथ्म को बदलने की ज़रूरत नहीं है, और अमूर्त अनुक्रम समान रहता है।

डेकोरेटर यह पैटर्न वस्तुओं के लिए उन्हें उपयोगी कार्यक्षमता देने के लिए रैपर बनाता है। हम इसे इस लेख का हिस्सा मानेंगे।

Java.io में, निम्न वर्ग पैटर्न लागू करते हैं:

नमूना जहां इसका उपयोग java.io में किया जाता है
अनुकूलक
टेम्पलेट विधि
डेकोरेटर

डेकोरेटर पैटर्न

आइए कल्पना करें कि हम घर के डिजाइन के लिए एक मॉडल का वर्णन कर रहे हैं।

सामान्य तौर पर, दृष्टिकोण इस तरह दिखता है:

प्रारंभ में, हमारे पास कई प्रकार के घरों का विकल्प होता है। न्यूनतम विन्यास छत के साथ एक मंजिल है। फिर हम अतिरिक्त मापदंडों को बदलने के लिए सभी प्रकार के सज्जाकारों का उपयोग करते हैं, जो स्वाभाविक रूप से घर की कीमत को प्रभावित करता है।

हम एक अमूर्त हाउस क्लास बनाते हैं:

public abstract class House {
	String info;

	public String getInfo() {
    	return info;
	}

	public abstract int getPrice();
}

यहां हमारे पास 2 तरीके हैं:

  • getInfo () हमारे घर के नाम और विशेषताओं के बारे में जानकारी देता है;
  • getPrice() वर्तमान हाउस कॉन्फ़िगरेशन की कीमत लौटाता है।

हमारे पास मानक हाउस कार्यान्वयन भी हैं — ईंट और लकड़ी:

public class BrickHouse extends House {

	public BrickHouse() {
    	info = "Brick House";
	}

	@Override
	public int getPrice() {
    	return 20_000;
	}
}

public class WoodenHouse extends House {

	public WoodenHouse() {
    	info = "Wooden House";
	}

	@Override
	public int getPrice() {
    	return 25_000;
	}
}

दोनों वर्ग हाउस क्लास को इनहेरिट करते हैं और इसकी मूल्य पद्धति को ओवरराइड करते हैं, एक मानक घर के लिए एक कस्टम मूल्य निर्धारित करते हैं। हम कंस्ट्रक्टर में नाम सेट करते हैं।

अगला, हमें डेकोरेटर क्लासेस लिखने की आवश्यकता है। ये वर्ग हाउस क्लास को भी इनहेरिट करेंगे । ऐसा करने के लिए, हम एक अमूर्त डेकोरेटर वर्ग बनाते हैं।

यहीं पर हम किसी वस्तु को बदलने के लिए अतिरिक्त तर्क देंगे। प्रारंभ में, कोई अतिरिक्त तर्क नहीं होगा और सार वर्ग खाली होगा।

abstract class HouseDecorator extends House {
}

अगला, हम डेकोरेटर कार्यान्वयन बनाते हैं। हम कई वर्ग बनाएंगे जो हमें घर में अतिरिक्त सुविधाएँ जोड़ने देंगे:

public class SecondFloor extends HouseDecorator {
	House house;

	public SecondFloor(House house) {
    	this.house = house;
	}

	@Override
	public int getPrice() {
    	return house.getPrice() + 20_000;
	}

	@Override
	public String getInfo() {
    	return house.getInfo() + " + second floor";
	}
}
एक डेकोरेटर जो हमारे घर में दूसरी मंजिल जोड़ता है

डेकोरेटर कंस्ट्रक्टर एक घर को स्वीकार करता है जिसे हम "सजाएंगे", यानी संशोधनों को जोड़ेंगे। और हम getPrice () और getInfo () विधियों को ओवरराइड करते हैं, पुराने के आधार पर नए अपडेट किए गए घर के बारे में जानकारी लौटाते हैं।

public class Garage extends HouseDecorator {

	House house;
	public Garage(House house) {
    	this.house = house;
	}

	@Override
	public int getPrice() {
    	return house.getPrice() + 5_000;
	}

	@Override
	public String getInfo() {
    	return house.getInfo() + " + garage";
	}
}
एक डेकोरेटर जो हमारे घर में गैरेज जोड़ता है

अब हम अपने घर को डेकोरेटर्स से अपडेट कर सकते हैं। ऐसा करने के लिए, हमें एक घर बनाने की जरूरत है:

House brickHouse = new BrickHouse();

अगला, हम अपना सेट करते हैंघरहमारे घर में गुजरने वाले नए डेकोरेटर के बराबर चर:

brickHouse = new SecondFloor(brickHouse);

हमाराघरचर अब दूसरी मंजिल वाला घर है।

आइए सज्जाकारों से जुड़े उपयोग के मामलों को देखें:

उदाहरण कोड उत्पादन
House brickHouse = new BrickHouse();

  System.out.println(brickHouse.getInfo());
  System.out.println(brickHouse.getPrice());

ईंट का मकान

20000

House brickHouse = new BrickHouse();

  brickHouse = new SecondFloor(brickHouse);

  System.out.println(brickHouse.getInfo());
  System.out.println(brickHouse.getPrice());

ब्रिक हाउस + दूसरी मंजिल

40000

House brickHouse = new BrickHouse();


  brickHouse = new SecondFloor(brickHouse);
  brickHouse = new Garage(brickHouse);

  System.out.println(brickHouse.getInfo());
  System.out.println(brickHouse.getPrice());

ब्रिक हाउस + दूसरी मंजिल + गैरेज

45000

House woodenHouse = new SecondFloor(new Garage(new WoodenHouse()));

  System.out.println(woodenHouse.getInfo());
  System.out.println(woodenHouse.getPrice());

लकड़ी का घर + गैरेज + दूसरी मंजिल

50000

House woodenHouse = new WoodenHouse();

  House woodenHouseWithGarage = new Garage(woodenHouse);

  System.out.println(woodenHouse.getInfo());
  System.out.println(woodenHouse.getPrice());

  System.out.println(woodenHouseWithGarage.getInfo());
  System.out.println(woodenHouseWithGarage.getPrice());

लकड़ी के घर

25000

लकड़ी का घर + गैरेज

30000

यह उदाहरण किसी वस्तु को डेकोरेटर के साथ अपग्रेड करने के लाभों को दर्शाता है। इसलिए हमने बदलाव नहीं कियालकड़ी के घरऑब्जेक्ट ही, लेकिन इसके बजाय पुराने के आधार पर एक नया ऑब्जेक्ट बनाया। यहाँ हम देख सकते हैं कि फायदे नुकसान के साथ आते हैं: हम हर बार मेमोरी में एक नया ऑब्जेक्ट बनाते हैं, जिससे मेमोरी की खपत बढ़ती है।

हमारे कार्यक्रम के इस यूएमएल आरेख को देखें:

एक डेकोरेटर के पास एक सुपर सरल कार्यान्वयन है और वस्तुओं को गतिशील रूप से बदलता है, उन्हें अपग्रेड करता है। डेकोरेटर्स को उनके कंस्ट्रक्टर्स द्वारा पहचाना जा सकता है, जो वर्तमान क्लास के समान सार प्रकार या इंटरफ़ेस के पैरामीटर ऑब्जेक्ट्स के रूप में लेते हैं। जावा में, इस पैटर्न का व्यापक रूप से I/O कक्षाओं में उपयोग किया जाता है।

उदाहरण के लिए, जैसा कि हमने पहले ही उल्लेख किया है, java.io.InputStream , OutputStream , Reader और Writer के सभी उपवर्गों में एक कंस्ट्रक्टर है जो समान वर्गों की वस्तुओं को स्वीकार करता है।