আমরা ইতিমধ্যে একটি সিঙ্গলটন বস্তুর ব্যবহার পর্যালোচনা করেছি, কিন্তু আপনি এখনও বুঝতে পারেন না যে এই কৌশলটি একটি ডিজাইন প্যাটার্ন, এবং এটিতে সবচেয়ে বেশি ব্যবহৃত একটি।

আসলে, এই নিদর্শন অনেক আছে, এবং তারা তাদের নির্দিষ্ট উদ্দেশ্য অনুযায়ী শ্রেণীবদ্ধ করা যেতে পারে.

প্যাটার্ন শ্রেণীবিভাগ

প্যাটার্ন প্রকার আবেদন
সৃজনশীল একটি প্রকার যা বস্তু তৈরির সমস্যা সমাধান করে
কাঠামোগত প্যাটার্ন যা আমাদের আর্কিটেকচারে একটি সঠিক এবং এক্সটেনসিবল ক্লাস শ্রেণীবিন্যাস তৈরি করতে দেয়
আচরণগত প্যাটার্নের এই ক্লাস্টার একটি প্রোগ্রামের বস্তুর মধ্যে নিরাপদ এবং সুবিধাজনক মিথস্ক্রিয়া সহজতর করে।

সাধারণত, একটি প্যাটার্ন এটি যে সমস্যার সমাধান করে তা দ্বারা চিহ্নিত করা হয়। জাভা নিয়ে কাজ করার সময় আমরা প্রায়শই সম্মুখীন হই এমন কয়েকটি নিদর্শন দেখে নেওয়া যাক:

প্যাটার্ন উদ্দেশ্য
সিঙ্গেলটন আমরা ইতিমধ্যেই এই প্যাটার্নের সাথে পরিচিত — আমরা এটি একটি ক্লাস তৈরি করতে এবং অ্যাক্সেস করতে ব্যবহার করি যাতে একাধিক উদাহরণ থাকতে পারে না।
পুনরাবৃত্তিকারী আমরা এই এক সঙ্গে পরিচিত. আমরা জানি যে এই প্যাটার্নটি আমাদের একটি সংগ্রহের বস্তুর অভ্যন্তরীণ উপস্থাপনা প্রকাশ না করেই পুনরাবৃত্তি করতে দেয়। এটি সংগ্রহের সাথে ব্যবহার করা হয়।
অ্যাডাপ্টার এই প্যাটার্নটি বেমানান বস্তুকে সংযুক্ত করে যাতে তারা একসাথে কাজ করতে পারে। আমি মনে করি অ্যাডাপ্টারের প্যাটার্নের নাম আপনাকে এটি ঠিক কী করে তা কল্পনা করতে সহায়তা করে। এখানে বাস্তব জীবনের একটি সহজ উদাহরণ: একটি প্রাচীর আউটলেটের জন্য একটি USB অ্যাডাপ্টার৷
টেমপ্লেট পদ্ধতি

একটি আচরণগত প্রোগ্রামিং প্যাটার্ন যা ইন্টিগ্রেশন সমস্যার সমাধান করে এবং আপনাকে অ্যালগরিদমের গঠন পরিবর্তন না করেই অ্যালগরিদমিক পদক্ষেপগুলি পরিবর্তন করতে দেয়।

কল্পনা করুন যে আমাদের কাছে অ্যাসেম্বলি পদক্ষেপগুলির একটি ক্রম আকারে একটি গাড়ি সমাবেশ অ্যালগরিদম রয়েছে:

চ্যাসিস -> বডি -> ইঞ্জিন -> কেবিন ইন্টেরিয়র

যদি আমরা একটি শক্তিশালী ফ্রেম, একটি আরও শক্তিশালী ইঞ্জিন, বা অতিরিক্ত আলো সহ একটি অভ্যন্তরীণ রাখি তবে আমাদের অ্যালগরিদম পরিবর্তন করতে হবে না এবং বিমূর্ত ক্রমটি একই থাকে।

ডেকোরেটর এই প্যাটার্ন বস্তুর জন্য তাদের দরকারী কার্যকারিতা দিতে wrappers তৈরি করে. আমরা এই নিবন্ধের অংশ হিসাবে বিবেচনা করা হবে.

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

এই উদাহরণটি একটি ডেকোরেটরের সাথে একটি বস্তুকে আপগ্রেড করার সুবিধার চিত্র তুলে ধরে। তাই আমরা পরিবর্তন নাকাঠের ঘরবস্তু নিজেই, কিন্তু পরিবর্তে পুরানো এক উপর ভিত্তি করে একটি নতুন বস্তু তৈরি. এখানে আমরা দেখতে পাচ্ছি যে সুবিধাগুলি অসুবিধাগুলির সাথে আসে: আমরা প্রতিবার মেমরিতে একটি নতুন বস্তু তৈরি করি, মেমরি খরচ বাড়াই।

আমাদের প্রোগ্রামের এই UML চিত্রটি দেখুন:

একটি ডেকোরেটরের একটি অতি সাধারণ বাস্তবায়ন রয়েছে এবং গতিশীলভাবে বস্তুগুলিকে পরিবর্তন করে, তাদের আপগ্রেড করে। ডেকোরেটরগুলি তাদের কনস্ট্রাক্টরদের দ্বারা স্বীকৃত হতে পারে, যা বর্তমান ক্লাসের মতো একই বিমূর্ত ধরণের বা ইন্টারফেসের প্যারামিটার অবজেক্ট হিসাবে নেয়। জাভাতে, এই প্যাটার্নটি I/O ক্লাসে ব্যাপকভাবে ব্যবহৃত হয়।

উদাহরণস্বরূপ, যেমনটি আমরা ইতিমধ্যেই উল্লেখ করেছি, java.io.InputStream , OutputStream , Reader এবং Writer- এর সমস্ত সাবক্লাসে একটি কনস্ট্রাক্টর রয়েছে যা একই ক্লাসের বস্তু গ্রহণ করে।