যখন পরিষ্কার, রক্ষণাবেক্ষণযোগ্য এবং দক্ষ কোড লেখার কথা আসে, তখন ডিজাইন প্যাটার্নগুলি সফ্টওয়্যার বিকাশের জগতে একটি গুরুত্বপূর্ণ ভূমিকা পালন করে। ডিজাইন প্যাটার্ন হল সাধারণ সমস্যাগুলির পুনর্ব্যবহারযোগ্য সমাধান যা ডেভেলপাররা সফ্টওয়্যার সিস্টেম ডিজাইন এবং তৈরি করার সময় সম্মুখীন হয়। তারা নির্দিষ্ট চ্যালেঞ্জগুলি সমাধান করার জন্য একটি কাঠামোগত পদ্ধতি প্রদান করে, এটি কোড তৈরি করা সহজ করে যা কেবল শক্তিশালী নয়, বোঝা এবং বজায় রাখাও সহজ।
অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং (OOP ) এ, নকশার প্যাটার্নগুলি নমনীয়তা, পুনঃব্যবহারযোগ্যতা এবং মাপযোগ্যতা প্রচার করে এমনভাবে আপনার কোড গঠনের জন্য নির্দেশিকা হিসাবে কাজ করে। তারা সর্বোত্তম অনুশীলন এবং ডিজাইনের নীতিগুলিকে অন্তর্ভুক্ত করে যা বিকশিত হয়েছে এবং প্রমাণিত সমাধানগুলিতে পাতিত হয়েছে।
নকশা প্যাটার্ন তিনটি প্রধান গ্রুপে শ্রেণীবদ্ধ করা যেতে পারে:
সৃজনশীল নিদর্শন: এই নিদর্শনগুলি বস্তু তৈরির প্রক্রিয়ার উপর ফোকাস করে, পরিস্থিতির জন্য উপযুক্ত উপায়ে বস্তু তৈরি করার চেষ্টা করে। তারা ইনস্ট্যান্টিয়েশন প্রক্রিয়াটিকে বিমূর্ত করে, এটিকে আরও নমনীয় এবং সিস্টেম থেকে স্বাধীন করে তোলে।
স্ট্রাকচারাল প্যাটার্নস: স্ট্রাকচারাল প্যাটার্নগুলি বস্তুর গঠন নিয়ে কাজ করে, বড়, আরও জটিল কাঠামো তৈরি করতে বস্তুর মধ্যে সম্পর্ক তৈরি করে। তারা সংজ্ঞায়িত করতে সাহায্য করে কিভাবে বস্তু এবং শ্রেণীকে একত্রিত করে নতুন কাঠামো তৈরি করা যায় এবং নতুন কার্যকারিতা প্রদান করা যায়।
আচরণগত নিদর্শন: আচরণগত নিদর্শনগুলি বস্তুর মধ্যে যোগাযোগের সাথে সম্পর্কিত, তারা কীভাবে মিথস্ক্রিয়া করে এবং দায়িত্ব বিতরণ করে তা নির্ধারণ করে। এই নিদর্শনগুলি আপনাকে সিস্টেমগুলি ডিজাইন করতে সাহায্য করে যেখানে বস্তুগুলি আরও নমনীয় এবং দক্ষ পদ্ধতিতে সহযোগিতা করে।
এখানে প্রতিটি বিভাগে কিছু সাধারণ নকশা প্যাটার্নের একটি তালিকা রয়েছে:
পর্যবেক্ষক প্যাটার্ন: বস্তুর মধ্যে এক-থেকে-অনেক নির্ভরতা সংজ্ঞায়িত করে, তাই যখন একটি বস্তুর অবস্থা পরিবর্তন হয়, তখন তার সমস্ত নির্ভরশীলকে স্বয়ংক্রিয়ভাবে অবহিত করা হয় এবং আপডেট করা হয়।
কৌশল প্যাটার্ন: অ্যালগরিদমগুলির একটি পরিবারকে সংজ্ঞায়িত করে, প্রতিটিকে এনক্যাপসুলেট করে এবং তাদের বিনিময়যোগ্য করে তোলে।
কমান্ড প্যাটার্ন: একটি অনুরোধকে একটি বস্তু হিসাবে এনক্যাপসুলেট করে, যার ফলে সারি, অনুরোধ এবং অপারেশন সহ ক্লায়েন্টদের প্যারামিটারাইজেশনের অনুমতি দেয়।
স্টেট প্যাটার্ন: একটি বস্তুকে তার অভ্যন্তরীণ অবস্থা পরিবর্তন করার সময় তার আচরণ পরিবর্তন করতে দেয়, আচরণটিকে আলাদা ক্লাসে মোড়ানো।
চেইন অফ রেসপনসিবিলিটি প্যাটার্ন: হ্যান্ডলারদের একটি চেইন বরাবর অনুরোধটি পাস করে, প্রতিটি হ্যান্ডলারকে অনুরোধটি প্রক্রিয়া করতে বা চেইনের পরবর্তী হ্যান্ডলারের কাছে পাঠানোর সিদ্ধান্ত নিতে দেয়।
ভিজিটর প্যাটার্ন: এটি একটি বস্তুর কাঠামোর উপাদানগুলির উপর সঞ্চালিত একটি অপারেশনকে প্রতিনিধিত্ব করে, আপনাকে উপাদানগুলির শ্রেণী পরিবর্তন না করেই নতুন ক্রিয়াকলাপ সংজ্ঞায়িত করতে সক্ষম করে৷
এই ব্লগে, আমরা এই ডিজাইন প্যাটার্নগুলির প্রতিটির মধ্যে অনুসন্ধান করব, ব্যাখ্যা প্রদান করব, বাস্তব-বিশ্ব ব্যবহারের ক্ষেত্রে, এবং জাভাস্ক্রিপ্ট কোড উদাহরণগুলি আপনাকে বুঝতে এবং আপনার প্রকল্পগুলিতে কার্যকরভাবে প্রয়োগ করতে সহায়তা করবে৷
সিঙ্গেলটন প্যাটার্ন হল একটি সৃজনশীল ডিজাইন প্যাটার্ন যা নিশ্চিত করে যে একটি ক্লাসের শুধুমাত্র একটি উদাহরণ আছে এবং সেই উদাহরণে একটি বিশ্বব্যাপী প্রবেশাধিকার প্রদান করে। এই প্যাটার্নটি বিশেষভাবে কার্যকর যখন আপনি আপনার অ্যাপ্লিকেশনে একটি ক্লাসের দৃষ্টান্তের সংখ্যা সীমিত করতে চান এবং একটি একক ভাগ করা উদাহরণে অ্যাক্সেস নিয়ন্ত্রণ করতে চান।
জাভাস্ক্রিপ্টে, সিঙ্গেলটন প্যাটার্ন প্রয়োগ করা তুলনামূলকভাবে সহজ, ভাষার নমনীয়তার জন্য ধন্যবাদ। কিভাবে জাভাস্ক্রিপ্টে একটি সিঙ্গেলটন তৈরি করা যায় তার একটি সহজ উদাহরণে ডুব দেওয়া যাক।
// Singleton instance let instance = null;
class Singleton { constructor() { if (!instance) { instance = this; // Your initialization code here } else { return instance; } } // Your methods and properties here }// Usage const singletonA = new Singleton(); const singletonB = new Singleton(); console.log(singletonA === singletonB); // Output: true (both variables reference the same instance)
এই উদাহরণে, আমরা একটি কনস্ট্রাক্টরের সাথে একটি সিঙ্গেলটন ক্লাস তৈরি করি যা পরীক্ষা করে যে একটি উদাহরণ ইতিমধ্যেই বিদ্যমান আছে কিনা। যদি একটি উদাহরণ বিদ্যমান না থাকে তবে এটি একটি তৈরি করে এবং এটিকে ইনস্ট্যান্স ভেরিয়েবলে বরাদ্দ করে। কনস্ট্রাক্টরের কাছে পরবর্তী কলগুলি বিদ্যমান দৃষ্টান্ত ফিরিয়ে দেয়, নিশ্চিত করে যে সিঙ্গেলটন ক্লাসের একটি মাত্র উদাহরণ রয়েছে।
সিঙ্গেলটন প্যাটার্নটি বিভিন্ন পরিস্থিতিতে দরকারী, যার মধ্যে রয়েছে:
যদিও সিঙ্গেলটন প্যাটার্নটি উপকারী হতে পারে, তবে এটি যথাযথভাবে ব্যবহার করা অপরিহার্য। সিঙ্গেলটন প্যাটার্নের অত্যধিক ব্যবহার শক্তভাবে সংযুক্ত কোড এবং বিশ্বব্যাপী অবস্থার দিকে পরিচালিত করতে পারে, যা আপনার অ্যাপ্লিকেশনটিকে বজায় রাখা এবং পরীক্ষা করা কঠিন করে তুলতে পারে। অতএব, ভাল এবং অসুবিধাগুলি ওজন করা এবং প্যাটার্নটি প্রয়োগ করা অত্যন্ত গুরুত্বপূর্ণ যেখানে এটি আপনার কোডবেসে সত্যিকারের মূল্য যোগ করে।
ফ্যাক্টরি প্যাটার্ন এবং অ্যাবস্ট্রাক্ট ফ্যাক্টরি প্যাটার্ন হল সৃজনশীল ডিজাইনের প্যাটার্ন যা বস্তুর সৃষ্টির সাথে ডিল করে, কিন্তু তারা তা বিভিন্ন উপায়ে করে এবং স্বতন্ত্র উদ্দেশ্য পূরণ করে। আসুন এই প্যাটার্নগুলির প্রতিটি অন্বেষণ করি এবং দেখুন কিভাবে সেগুলি জাভাস্ক্রিপ্টে প্রয়োগ করা যেতে পারে।
ফ্যাক্টরি প্যাটার্ন হল একটি সৃজনশীল প্যাটার্ন যা অবজেক্ট তৈরির জন্য একটি ইন্টারফেস প্রদান করে কিন্তু সাবক্লাসগুলিকে তৈরি করা বস্তুর ধরন পরিবর্তন করতে দেয়। এটি বস্তু তৈরির প্রক্রিয়াকে এনক্যাপসুলেট করে, এটিকে আরও নমনীয় করে এবং ক্লায়েন্ট কোড থেকে ডিকপল করে।
// Product class class Product { constructor(name) { this.name = name; } }
// Factory for creating products class ProductFactory { createProduct(name) { return new Product(name); } }// Usage const factory = new ProductFactory(); const productA = factory.createProduct('Product A'); const productB = factory.createProduct('Product B');console.log(productA.name); // Output: 'Product A' console.log(productB.name); // Output: 'Product B'
এই উদাহরণে, প্রোডাক্ট ফ্যাক্টরি প্রোডাক্ট ক্লাসের উদাহরণ তৈরি করার জন্য দায়ী। এটি তৈরির প্রক্রিয়াকে বিমূর্ত করে, আপনাকে কারখানার প্রসারিত করে বিভিন্ন ধরনের পণ্য তৈরি করতে দেয়।
অ্যাবস্ট্রাক্ট ফ্যাক্টরি প্যাটার্ন হল আরেকটি সৃজনশীল প্যাটার্ন যা তাদের কংক্রিট ক্লাস নির্দিষ্ট না করেই সম্পর্কিত বা নির্ভরশীল বস্তুর পরিবার তৈরি করার জন্য একটি ইন্টারফেস প্রদান করে। এটি আপনাকে বস্তুর সেট তৈরি করতে দেয় যা একসাথে সুরেলাভাবে কাজ করে।
// Abstract Product classes class Button { render() {} }
class Checkbox { render() {} }// Concrete Product classes class MacButton extends Button { render() { return 'Render Mac button'; } }class MacCheckbox extends Checkbox { render() { return 'Render Mac checkbox'; } }class WindowsButton extends Button { render() { return 'Render Windows button'; } }class WindowsCheckbox extends Checkbox { render() { return 'Render Windows checkbox'; } }// Abstract Factory interface class GUIFactory { createButton() {} createCheckbox() {} }// Concrete Factories class MacFactory extends GUIFactory { createButton() { return new MacButton(); } createCheckbox() { return new MacCheckbox(); } }class WindowsFactory extends GUIFactory { createButton() { return new WindowsButton(); } createCheckbox() { return new WindowsCheckbox(); } }// Usage function createUI(factory) { const button = factory.createButton(); const checkbox = factory.createCheckbox(); return { button, checkbox }; }const macUI = createUI(new MacFactory()); console.log(macUI.button.render()); // Output: 'Render Mac button' console.log(macUI.checkbox.render()); // Output: 'Render Mac checkbox'const windowsUI = createUI(new WindowsFactory()); console.log(windowsUI.button.render()); // Output: 'Render Windows button' console.log(windowsUI.checkbox.render()); // Output: 'Render Windows checkbox'
এই উদাহরণে, আমাদের দুটি কংক্রিট কারখানা রয়েছে, ম্যাকফ্যাক্টরি এবং উইন্ডোজফ্যাক্টরি, প্রতিটি তাদের নিজ নিজ প্ল্যাটফর্মের জন্য সম্পর্কিত UI উপাদানগুলির (বোতাম এবং চেকবক্স) সেট তৈরি করতে সক্ষম। CreateUI ফাংশন আপনাকে উপযুক্ত কারখানা ব্যবহার করে একটি নির্দিষ্ট প্ল্যাটফর্মের জন্য একটি সমন্বিত UI তৈরি করতে দেয়।
কখন কোন প্যাটার্ন ব্যবহার করবেন:
বিল্ডার প্যাটার্ন হল একটি সৃজনশীল নকশার প্যাটার্ন যা একটি জটিল বস্তুর নির্মাণকে তার উপস্থাপনা থেকে আলাদা করে, একই নির্মাণ প্রক্রিয়াকে বিভিন্ন উপস্থাপনা তৈরি করতে দেয়। এই প্যাটার্নটি বিশেষভাবে উপযোগী হয় যখন আপনার কাছে প্রচুর সংখ্যক বৈশিষ্ট্য সহ একটি বস্তু থাকে এবং আপনি নমনীয়তা বজায় রেখে উদাহরণ তৈরিকে সহজ করতে চান।
জাভাস্ক্রিপ্টে, বিল্ডার প্যাটার্নটি প্রায়শই একটি বিল্ডার ক্লাস বা অবজেক্ট ব্যবহার করে প্রয়োগ করা হয় যা জটিল অবজেক্টের ধাপে ধাপে নির্মাণের নির্দেশনা দেয়। আসুন এটি কীভাবে কাজ করে তা বোঝার জন্য একটি উদাহরণে ডুব দেওয়া যাক।
// Product class with multiple properties class Product { constructor() { this.name = ''; this.price = 0; this.color = 'white'; // ... other properties }
// Additional methods can be defined here }// Builder for creating Product instances class ProductBuilder { constructor() { this.product = new Product(); } setName(name) { this.product.name = name; return this; // Return the builder for method chaining } setPrice(price) { this.product.price = price; return this; } setColor(color) { this.product.color = color; return this; } // Other methods to set additional properties build() { return this.product; // Return the fully constructed product } }// Usage const builder = new ProductBuilder();const productA = builder .setName('Product A') .setPrice(99.99) .setColor('blue') .build();const productB = builder .setName('Product B') .setPrice(49.99) .build();console.log(productA); console.log(productB);
এই উদাহরণে, আমাদের একাধিক বৈশিষ্ট্য সহ একটি পণ্য শ্রেণি রয়েছে। ProductBuilder ক্লাস ধাপে ধাপে প্রতিটি সম্পত্তি সেট করার পদ্ধতি প্রদান করে পণ্যের উদাহরণ তৈরি করতে সাহায্য করে। মেথড চেইনিং আপনাকে সাবলীল এবং পঠনযোগ্য উপায়ে একাধিক বৈশিষ্ট্য সেট করতে দেয়। অবশেষে, বিল্ড পদ্ধতি সম্পূর্ণরূপে তৈরি পণ্যের উদাহরণ প্রদান করে।
বিল্ডার প্যাটার্ন বিভিন্ন পরিস্থিতিতে উপকারী, সহ:
যদিও বিল্ডার প্যাটার্ন অনেক সুবিধা প্রদান করে, এটি মনে রাখা গুরুত্বপূর্ণ যে এটি আপনার কোডবেসে জটিলতা যোগ করে, বিশেষ করে যদি নির্মাণ করা বস্তুগুলি তুলনামূলকভাবে সহজ হয়। অতএব, বিল্ডার দ্বারা প্রবর্তিত জটিলতা আপনার নির্দিষ্ট ব্যবহারের ক্ষেত্রে ন্যায়সঙ্গত কিনা তা মূল্যায়ন করা অপরিহার্য।
প্রোটোটাইপ প্যাটার্ন হল একটি সৃজনশীল ডিজাইন প্যাটার্ন যা আপনাকে একটি বিদ্যমান বস্তুর অনুলিপি করে নতুন বস্তু তৈরি করতে দেয়, যা প্রোটোটাইপ নামে পরিচিত। এটি তৈরি করার জন্য অবজেক্টের সঠিক শ্রেণি নির্দিষ্ট না করেই অবজেক্ট তৈরির প্রচার করে। এই প্যাটার্নটি বিশেষভাবে কার্যকর যখন আপনি দক্ষতার সাথে জটিল বস্তুর উদাহরণ তৈরি করতে চান।
জাভাস্ক্রিপ্টে, প্রোটোটাইপ প্যাটার্নটি অন্তর্নির্মিত prototype
বৈশিষ্ট্য এবং Object.create()
পদ্ধতির সাথে ঘনিষ্ঠভাবে সম্পর্কিত। আসুন জেনে নেই কিভাবে জাভাস্ক্রিপ্টে প্রোটোটাইপ প্যাটার্ন প্রয়োগ এবং ব্যবহার করতে হয়।
// Prototype object const vehiclePrototype = { init(make, model) { this.make = make; this.model = model; }, getDetails() { return `${this.make} ${this.model}`; }, };
// Create new instances using the prototype const car1 = Object.create(vehiclePrototype); car1.init('Toyota', 'Camry');const car2 = Object.create(vehiclePrototype); car2.init('Honda', 'Civic');console.log(car1.getDetails()); // Output: 'Toyota Camry' console.log(car2.getDetails()); // Output: 'Honda Civic'
এই উদাহরণে, আমরা একটি vehiclePrototype
অবজেক্টকে সংজ্ঞায়িত করি যা সমস্ত যানবাহনে সাধারণ পদ্ধতি এবং বৈশিষ্ট্য সহ। আমরা এই প্রোটোটাইপের উপর ভিত্তি করে নতুন উদাহরণ (car1 এবং car2) তৈরি করতে Object.create()
ব্যবহার করি। এই দৃষ্টান্তগুলি প্রোটোটাইপ থেকে বৈশিষ্ট্য এবং পদ্ধতিগুলিকে উত্তরাধিকার সূত্রে প্রাপ্ত করে, যা আপনাকে দক্ষতার সাথে ভাগ করা আচরণের সাথে নতুন বস্তু তৈরি করতে দেয়।
প্রোটোটাইপ প্যাটার্নটি বিভিন্ন পরিস্থিতিতে মূল্যবান, যার মধ্যে রয়েছে:
যদিও প্রোটোটাইপ প্যাটার্নটি দরকারী, এটির কিছু বিবেচনা রয়েছে:
অবজেক্ট পুল প্যাটার্ন হল একটি সৃজনশীল নকশার প্যাটার্ন যা বস্তুর সৃষ্টি এবং ধ্বংসের ওভারহেড কমিয়ে আনতে পুনরায় ব্যবহারযোগ্য বস্তুর পুল পরিচালনা করে। এটি বিশেষভাবে কার্যকর যখন বস্তু তৈরি এবং ধ্বংস করা ব্যয়বহুল বা সম্পদ-নিবিড়। অবজেক্ট পুল প্যাটার্ন স্ক্র্যাচ থেকে নতুন তৈরি করার পরিবর্তে বস্তুর পুনর্ব্যবহার এবং পুনর্ব্যবহারের মাধ্যমে কর্মক্ষমতা এবং সম্পদের ব্যবহার উন্নত করতে সাহায্য করে।
জাভাস্ক্রিপ্টে, আপনি অ্যারে বা কাস্টম পুল ম্যানেজমেন্ট ক্লাস ব্যবহার করে অবজেক্ট পুল প্যাটার্ন বাস্তবায়ন করতে পারেন। একটি সাধারণ উদাহরণ দিয়ে এই প্যাটার্নটি কীভাবে কাজ করে তা অন্বেষণ করা যাক।
class ObjectPool { constructor(maxSize) { this.maxSize = maxSize; this.pool = []; }
create() { if (this.pool.length < this.maxSize) { // Create a new object and add it to the pool const obj = { /* Your object initialization code here */ }; this.pool.push(obj); return obj; } else { // Pool is full, cannot create more objects console.log('Pool is full. Cannot create more objects.'); return null; } } reuse() { if (this.pool.length > 0) { // Reuse an object from the pool return this.pool.pop(); } else { // Pool is empty, no objects available for reuse console.log('Pool is empty. No objects available for reuse.'); return null; } } release(obj) { // Release an object back to the pool for reuse this.pool.push(obj); } }// Usage const pool = new ObjectPool(5); // Create a pool with a maximum size of 5 objectsconst obj1 = pool.create(); const obj2 = pool.create(); const obj3 = pool.create();pool.release(obj2); // Release obj2 back to the pool for reuseconst obj4 = pool.reuse(); // Reuse an object from the pool (obj2)
এই উদাহরণে, আমরা একটি অবজেক্টপুল ক্লাস তৈরি করি যা বস্তুর পুল পরিচালনা করে। তৈরি পদ্ধতিটি নতুন বস্তু তৈরি করে যখন পুলটি পূর্ণ না হয়, পুনঃব্যবহার পদ্ধতি পুনঃব্যবহারের জন্য পুল থেকে একটি বস্তু পুনরুদ্ধার করে এবং রিলিজ পদ্ধতি ভবিষ্যতে ব্যবহারের জন্য পুলে একটি বস্তু ফিরিয়ে দেয়।
অবজেক্ট পুল প্যাটার্ন বিভিন্ন পরিস্থিতিতে দরকারী, যার মধ্যে রয়েছে:
অবজেক্ট পুল প্যাটার্ন কর্মক্ষমতা সুবিধা প্রদান করে, নিম্নলিখিত বিবেচনা করা গুরুত্বপূর্ণ:
অ্যাডাপ্টার প্যাটার্ন হল একটি স্ট্রাকচারাল ডিজাইন প্যাটার্ন যা বেমানান ইন্টারফেস সহ বস্তুগুলিকে একসাথে কাজ করতে দেয়। এটি দুটি বেমানান ইন্টারফেসের মধ্যে একটি সেতু হিসাবে কাজ করে, তাদের উত্স কোড পরিবর্তন না করেই তাদের সামঞ্জস্যপূর্ণ করে তোলে। এই প্যাটার্নটি বিশেষভাবে উপযোগী যখন আপনাকে বিদ্যমান কোডটি একত্রিত করতে বা ব্যবহার করতে হবে যা আপনার অ্যাপ্লিকেশনের প্রয়োজনীয়তার সাথে পুরোপুরি খাপ খায় না।
জাভাস্ক্রিপ্টে, অ্যাডাপ্টার প্যাটার্নটি ক্লাস বা ফাংশন ব্যবহার করে প্রয়োগ করা যেতে পারে যা বেমানান ইন্টারফেসকে মোড়ানো বা অভিযোজিত করে। আসুন একটি বাস্তব উদাহরণ সহ জাভাস্ক্রিপ্টে অ্যাডাপ্টার প্যাটার্ন কীভাবে প্রয়োগ এবং ব্যবহার করা যায় তা অন্বেষণ করি।
ধরুন আপনার কাছে OldSystem
নামে একটি বিদ্যমান ক্লাস রয়েছে যার নাম legacyRequest
নামে একটি পদ্ধতি রয়েছে:
class OldSystem { legacyRequest() { return 'Data from the legacy system'; } }
এখন, আপনি আপনার আধুনিক অ্যাপ্লিকেশনে এই লিগ্যাসি সিস্টেমটি ব্যবহার করতে চান যা একটি ভিন্ন ইন্টারফেসের প্রত্যাশা করে। আপনি এই মত একটি অ্যাডাপ্টার ক্লাস বা ফাংশন তৈরি করতে পারেন:
class Adapter { constructor(oldSystem) { this.oldSystem = oldSystem; }
newRequest() { const legacyData = this.oldSystem.legacyRequest(); // Adapt the data or perform any necessary transformations return `Adapted: ${legacyData}`; } }
এখন, আপনি আপনার আধুনিক অ্যাপ্লিকেশনের সাথে লিগ্যাসি সিস্টেমকে সামঞ্জস্যপূর্ণ করতে অ্যাডাপ্টার ক্লাস ব্যবহার করতে পারেন:
const oldSystem = new OldSystem(); const adapter = new Adapter(oldSystem);
const result = adapter.newRequest(); console.log(result); // Output: 'Adapted: Data from the legacy system'
এই উদাহরণে, অ্যাডাপ্টার ক্লাস ওল্ডসিস্টেমকে মুড়ে দেয় এবং একটি নতুন ইন্টারফেস প্রদান করে, নতুন অনুরোধ, যা আপনার আধুনিক অ্যাপ্লিকেশনের সাথে সামঞ্জস্যপূর্ণ।
অ্যাডাপ্টার প্যাটার্নটি বিভিন্ন পরিস্থিতিতে মূল্যবান, যার মধ্যে রয়েছে:
যদিও অ্যাডাপ্টার প্যাটার্ন নমনীয়তা এবং সামঞ্জস্য প্রদান করে, এটি কয়েকটি পয়েন্ট বিবেচনা করা অপরিহার্য:
ডেকোরেটর প্যাটার্ন হল একটি স্ট্রাকচারাল ডিজাইন প্যাটার্ন যা আপনাকে বস্তুর বিদ্যমান কোড পরিবর্তন না করে গতিশীলভাবে নতুন আচরণ বা দায়িত্ব যোগ করতে দেয়। এটি ডেকোরেটর বস্তুর সাথে মোড়ানো বস্তুর কার্যকারিতা প্রসারিত করার একটি শক্তিশালী উপায়। এই প্যাটার্নটি "এক্সটেনশনের জন্য উন্মুক্ত, কিন্তু পরিবর্তনের জন্য বন্ধ" নীতিকে প্রচার করে, যার মূল বাস্তবায়ন পরিবর্তন না করে বস্তুতে নতুন বৈশিষ্ট্য যোগ করা সহজ করে তোলে।
জাভাস্ক্রিপ্টে, ডেকোরেটর প্যাটার্নটি ক্লাস এবং অবজেক্ট কম্পোজিশন ব্যবহার করে প্রয়োগ করা যেতে পারে। আসুন একটি বাস্তব উদাহরণ সহ জাভাস্ক্রিপ্টে ডেকোরেটর প্যাটার্ন কীভাবে প্রয়োগ এবং ব্যবহার করা যায় তা অন্বেষণ করি।
ধরুন আপনার একটি বেস ক্লাস Coffee
আছে:
class Coffee { cost() { return 5; // Base cost of a regular coffee } } Now, you want to add decorators to your coffee to customize it with additional options, such as milk and sugar:
javascript Copy code class MilkDecorator { constructor(coffee) { this.coffee = coffee; } cost() { return this.coffee.cost() + 2; // Adding the cost of milk } }class SugarDecorator { constructor(coffee) { this.coffee = coffee; } cost() { return this.coffee.cost() + 1; // Adding the cost of sugar } }
তারপর আপনি এই মত সজ্জিত কফি উদাহরণ তৈরি করতে পারেন:
const regularCoffee = new Coffee(); const coffeeWithMilk = new MilkDecorator(regularCoffee); const coffeeWithMilkAndSugar = new SugarDecorator(coffeeWithMilk);
console.log(regularCoffee.cost()); // Output: 5 console.log(coffeeWithMilk.cost()); // Output: 7 console.log(coffeeWithMilkAndSugar.cost()); // Output: 8
এই উদাহরণে, আমাদের কাছে কফি ক্লাস একটি বেস কফি প্রতিনিধিত্ব করে। MilkDecorator এবং SugarDecorator ক্লাসগুলি হল ডেকোরেটর যেগুলি একটি কফির বস্তুকে মোড়ানো এবং যথাক্রমে দুধ এবং চিনির দাম, মূল খরচের সাথে যোগ করে।
ডেকোরেটর প্যাটার্নটি বিভিন্ন পরিস্থিতিতে মূল্যবান, যার মধ্যে রয়েছে:
যদিও ডেকোরেটর প্যাটার্নটি বহুমুখী, তবে কয়েকটি বিবেচনা মাথায় রাখা গুরুত্বপূর্ণ:
প্রক্সি প্যাটার্ন হল একটি স্ট্রাকচারাল ডিজাইন প্যাটার্ন যা অন্য বস্তুর অ্যাক্সেস নিয়ন্ত্রণ করার জন্য একটি সারোগেট বা স্থানধারক প্রদান করে। এটি লক্ষ্য বস্তুর চারপাশে একটি মধ্যস্থতাকারী বা মোড়ক হিসাবে কাজ করে, আপনাকে অতিরিক্ত আচরণ যোগ করতে, অ্যাক্সেস নিয়ন্ত্রণ করতে বা অবজেক্ট তৈরিতে বিলম্ব করতে দেয়। প্রক্সি প্যাটার্ন বিভিন্ন পরিস্থিতিতে কার্যকর, যেমন অলস লোডিং, অ্যাক্সেস নিয়ন্ত্রণ এবং লগিং বাস্তবায়ন।
জাভাস্ক্রিপ্টে, বিল্ট-ইন Proxy
অবজেক্ট ব্যবহার করে প্রক্সি তৈরি করা যায়। আসুন ব্যবহারিক উদাহরণ সহ জাভাস্ক্রিপ্টে প্রক্সি প্যাটার্ন কীভাবে প্রয়োগ এবং ব্যবহার করা যায় তা অন্বেষণ করি।
ধরুন আপনার কাছে একটি সম্পদ-নিবিড় বস্তু আছে যেটি আপনি অলসভাবে লোড করতে চান যখন এটি প্রয়োজন হয়। আপনি অলস লোডিং অর্জন করতে একটি প্রক্সি ব্যবহার করতে পারেন:
class ExpensiveResource { constructor() { console.log('Creating an expensive resource...'); }
fetchData() { console.log('Fetching data...'); } }class LazyResourceProxy { constructor() { this.resource = null; } fetchData() { if (!this.resource) { this.resource = new ExpensiveResource(); } this.resource.fetchData(); } }// Usage const lazyResource = new LazyResourceProxy(); // The actual resource is created and data is fetched only when needed lazyResource.fetchData();
এই উদাহরণে, LazyResourceProxy এক্সপেনসিভ রিসোর্সের জন্য একটি সারোগেট হিসাবে কাজ করে, প্রকৃত সম্পদ তৈরি করে যখন fetchData পদ্ধতিটি প্রথমবার কল করা হয়।
আপনি বস্তু এবং তাদের বৈশিষ্ট্য অ্যাক্সেস নিয়ন্ত্রণ করতে প্রক্সি ব্যবহার করতে পারেন:
const user = { username: 'john_doe', password: 'secret123', };
const userProxy = new Proxy(user, { get(target, property) { if (property === 'password') { throw new Error('Access denied to password.'); } return target[property]; }, });console.log(userProxy.username); // Output: 'john_doe' console.log(userProxy.password); // Throws an error: 'Access denied to password.'
এই উদাহরণে, প্রক্সি গেট অপারেশনকে বাধা দেয় এবং পাসওয়ার্ড সম্পত্তিতে অ্যাক্সেস সীমাবদ্ধ করে।
প্রক্সি প্যাটার্নটি বিভিন্ন পরিস্থিতিতে মূল্যবান, যার মধ্যে রয়েছে:
প্রক্সি প্যাটার্ন ব্যবহার করার সময়, নিম্নলিখিত বিবেচনাগুলি মনে রাখবেন:
কম্পোজিট প্যাটার্ন হল একটি স্ট্রাকচারাল ডিজাইন প্যাটার্ন যা আপনাকে আংশিক-সম্পূর্ণ শ্রেণিবিন্যাসের প্রতিনিধিত্ব করতে গাছের মতো কাঠামোতে বস্তু রচনা করতে দেয়। এটি ক্লায়েন্টদের পৃথক বস্তু এবং বস্তুর রচনাগুলিকে সমানভাবে আচরণ করতে দেয়। কম্পোজিট প্যাটার্নটি বিশেষভাবে উপযোগী যখন আপনাকে একটি সামঞ্জস্যপূর্ণ ইন্টারফেস বজায় রেখে ছোট, সম্পর্কিত বস্তুর সমন্বয়ে গঠিত জটিল কাঠামোর সাথে কাজ করতে হবে।
জাভাস্ক্রিপ্টে, আপনি ক্লাস বা অবজেক্ট ব্যবহার করে কম্পোজিট প্যাটার্ন বাস্তবায়ন করতে পারেন যা একটি সাধারণ ইন্টারফেস ভাগ করে, আপনাকে শ্রেণীবদ্ধ কাঠামো তৈরি করতে সক্ষম করে। আসুন ব্যবহারিক উদাহরণ সহ জাভাস্ক্রিপ্টে কম্পোজিট প্যাটার্ন কীভাবে বাস্তবায়ন এবং ব্যবহার করা যায় তা অন্বেষণ করি।
ধরুন আপনি একটি গ্রাফিক ডিজাইন অ্যাপ্লিকেশন তৈরি করছেন যা সহজ আকার এবং আকারের জটিল রচনা উভয়ের সাথে কাজ করতে হবে (যেমন, গ্রুপ)। আপনি এই অনুক্রমের প্রতিনিধিত্ব করতে কম্পোজিট প্যাটার্ন ব্যবহার করতে পারেন:
// Component interface class Graphic { draw() {} }
// Leaf class (represents simple shapes) class Circle extends Graphic { constructor() { super(); // Circle-specific properties and methods } draw() { // Draw a circle } }// Composite class (represents groups of shapes) class Group extends Graphic { constructor() { super(); this.graphics = []; } add(graphic) { this.graphics.push(graphic); } draw() { // Draw each graphic in the group this.graphics.forEach((graphic) => graphic.draw()); } }// Usage const circle1 = new Circle(); const circle2 = new Circle(); const group = new Group();group.add(circle1); group.add(circle2);group.draw(); // Draws both circles in the group
এই উদাহরণে, গ্রাফিক ক্লাস কম্পোনেন্ট ইন্টারফেস হিসাবে কাজ করে। সার্কেল বর্গ সাধারণ আকারের প্রতিনিধিত্ব করে, যখন গ্রুপ বর্গ আকারের রচনাগুলিকে প্রতিনিধিত্ব করে। সার্কেল এবং গ্রুপ উভয় ক্লাসই ড্র পদ্ধতি প্রয়োগ করে, আপনাকে রেন্ডার করার সময় তাদের সাথে সমানভাবে আচরণ করতে দেয়।
কম্পোজিট প্যাটার্নটি বিভিন্ন পরিস্থিতিতে মূল্যবান, যার মধ্যে রয়েছে:
কম্পোজিট প্যাটার্নের সাথে কাজ করার সময়, নিম্নলিখিতগুলি বিবেচনা করুন:
ব্রিজ প্যাটার্ন হল একটি স্ট্রাকচারাল ডিজাইন প্যাটার্ন যা একটি বস্তুর বিমূর্ততাকে এর বাস্তবায়ন থেকে আলাদা করে। এটি আপনাকে উভয়ের মধ্যে একটি সেতু তৈরি করতে দেয়, তাদের স্বাধীনভাবে পরিবর্তিত হতে সক্ষম করে। এই প্যাটার্নটি বিশেষভাবে উপযোগী যখন আপনি একটি বিমূর্ততা এবং এর বাস্তবায়নের মধ্যে একটি স্থায়ী বাঁধন এড়াতে চান, আপনার কোডটিকে আরও নমনীয় এবং বজায় রাখতে পারেন।
জাভাস্ক্রিপ্টে, ব্রিজ প্যাটার্নটি ক্লাস এবং অবজেক্ট ব্যবহার করে প্রয়োগ করা যেতে পারে যা বিমূর্তকরণের জন্য একটি বিমূর্ত ইন্টারফেস এবং বিভিন্ন প্ল্যাটফর্ম বা বৈশিষ্ট্যগুলির জন্য বিভিন্ন কংক্রিট বাস্তবায়ন প্রদান করে। আসুন ব্যবহারিক উদাহরণ সহ জাভাস্ক্রিপ্টে ব্রিজ প্যাটার্ন কীভাবে প্রয়োগ এবং ব্যবহার করা যায় তা অন্বেষণ করি।
ধরুন আপনি একটি অঙ্কন অ্যাপ্লিকেশন তৈরি করছেন যা ওয়েব ব্রাউজার এবং মোবাইল ডিভাইসের মতো বিভিন্ন প্ল্যাটফর্মে আকার রেন্ডার করতে পারে। রেন্ডারিং লজিক (বাস্তবায়ন) থেকে অঙ্কন আকার (বিমূর্ততা) আলাদা করতে আপনি ব্রিজ প্যাটার্ন ব্যবহার করতে পারেন:
// Abstraction class Shape { constructor(renderer) { this.renderer = renderer; }
draw() { // Delegating the drawing to the specific renderer this.renderer.renderShape(this); } }// Implementor interface class Renderer { renderShape(shape) {} }// Concrete Implementors class WebRenderer extends Renderer { renderShape(shape) { console.log(`Drawing on the web: ${shape.constructor.name}`); } }class MobileRenderer extends Renderer { renderShape(shape) { console.log(`Drawing on mobile: ${shape.constructor.name}`); } }// Concrete Abstractions (Shapes) class Circle extends Shape { constructor(renderer) { super(renderer); } }class Square extends Shape { constructor(renderer) { super(renderer); } }// Usage const webRenderer = new WebRenderer(); const mobileRenderer = new MobileRenderer();const circle = new Circle(webRenderer); const square = new Square(mobileRenderer);circle.draw(); // Output: Drawing on the web: Circle square.draw(); // Output: Drawing on mobile: Square
এই উদাহরণে, শেপ ক্লাস বিমূর্ততা (আকারগুলি আঁকতে হবে) প্রতিনিধিত্ব করে এবং রেন্ডারার শ্রেণীটি বাস্তবায়নকারী ইন্টারফেস (প্ল্যাটফর্ম-নির্দিষ্ট রেন্ডারিং লজিক) প্রতিনিধিত্ব করে। বিভিন্ন কংক্রিট বাস্তবায়নকারী (WebRenderer এবং MobileRenderer) যথাক্রমে ওয়েব এবং মোবাইল প্ল্যাটফর্মের জন্য রেন্ডারিং লজিক প্রদান করে। বৃত্ত এবং বর্গাকার শ্রেণী হল কংক্রিট বিমূর্ততা যা আকারের প্রতিনিধিত্ব করে।
ব্রিজ প্যাটার্নটি বিভিন্ন পরিস্থিতিতে মূল্যবান, যার মধ্যে রয়েছে:
সেতু প্যাটার্ন ব্যবহার করার সময়, নিম্নলিখিত বিবেচনা করুন:
ফ্লাইওয়েট প্যাটার্ন হল একটি স্ট্রাকচারাল ডিজাইন প্যাটার্ন যার লক্ষ্য মেমরি খরচ কমানো এবং বস্তুর সাধারণ অংশ ভাগ করে কর্মক্ষমতা উন্নত করা। এটি একটি বস্তুর অভ্যন্তরীণ অবস্থা (ভাগ করা এবং অপরিবর্তনীয়) এর বহিরাগত অবস্থা (অনন্য এবং প্রসঙ্গ-নির্ভর) থেকে আলাদা করে এটি অর্জন করে। এই প্যাটার্নটি বিশেষভাবে উপযোগী হয় যখন আপনার কাছে প্রচুর সংখ্যক অনুরূপ বস্তু থাকে এবং মেমরির পদচিহ্ন কমাতে চান।
জাভাস্ক্রিপ্টে, আপনি ভাগ করা অভ্যন্তরীণ অবস্থা এবং স্বতন্ত্র বহিরাগত অবস্থার প্রতিনিধিত্ব করতে ক্লাস বা অবজেক্ট ব্যবহার করে ফ্লাইওয়েট প্যাটার্ন বাস্তবায়ন করতে পারেন। আসুন ব্যবহারিক উদাহরণ সহ জাভাস্ক্রিপ্টে ফ্লাইওয়েট প্যাটার্ন কীভাবে প্রয়োগ এবং ব্যবহার করা যায় তা অন্বেষণ করি।
ধরুন আপনি একটি টেক্সট এডিটর তৈরি করছেন যাতে প্রচুর পরিমাণে পাঠ্য প্রদর্শন করতে হবে। প্রতিটি অক্ষরের জন্য একটি পৃথক বস্তু তৈরি করার পরিবর্তে, আপনি অক্ষর বস্তুগুলিকে ভাগ করতে ফ্লাইওয়েট প্যাটার্ন ব্যবহার করতে পারেন যখন তাদের একই অন্তর্নিহিত বৈশিষ্ট্য থাকে (যেমন, ফন্ট এবং আকার):
class Character { constructor(char, font, size) { this.char = char; this.font = font; this.size = size; }
render() { console.log(`Rendering character "${this.char}" in ${this.font}, size ${this.size}`); } }class CharacterFactory { constructor() { this.characters = {}; } getCharacter(char, font, size) { const key = `${char}-${font}-${size}`; if (!this.characters[key]) { this.characters[key] = new Character(char, font, size); } return this.characters[key]; } }// Usage const factory = new CharacterFactory();const charA1 = factory.getCharacter('A', 'Arial', 12); const charA2 = factory.getCharacter('A', 'Arial', 12); const charB = factory.getCharacter('B', 'Times New Roman', 14);charA1.render(); // Output: Rendering character "A" in Arial, size 12 charA2.render(); // Output: Rendering character "A" in Arial, size 12 (shared instance) charB.render(); // Output: Rendering character "B" in Times New Roman, size 14
এই উদাহরণে, ক্যারেক্টার ক্লাস অক্ষর নিজেই, ফন্ট এবং আকারের মতো অন্তর্নিহিত বৈশিষ্ট্য সহ স্বতন্ত্র অক্ষরগুলিকে উপস্থাপন করে। ক্যারেক্টারফ্যাক্টরি ক্লাস নিশ্চিত করে যে একই অন্তর্নিহিত বৈশিষ্ট্য সহ অক্ষরগুলি সদৃশ না করে ভাগ করা হয়েছে।
ফ্লাইওয়েট প্যাটার্নটি বিভিন্ন পরিস্থিতিতে মূল্যবান, যার মধ্যে রয়েছে:
ফ্লাইওয়েট প্যাটার্ন ব্যবহার করার সময়, নিম্নলিখিতগুলি বিবেচনা করুন:
অবজারভার প্যাটার্ন হল একটি আচরণগত নকশা প্যাটার্ন যা বস্তুর মধ্যে এক থেকে একাধিক নির্ভরতা স্থাপন করে। এটি একটি বস্তুকে (বিষয় বা পর্যবেক্ষণযোগ্য) একাধিক পর্যবেক্ষককে (শ্রোতাদের) তার অবস্থা বা ডেটার পরিবর্তন সম্পর্কে অবহিত করতে দেয়। এই প্যাটার্নটি সাধারণত ডিস্ট্রিবিউটেড ইভেন্ট হ্যান্ডলিং সিস্টেম বাস্তবায়নের জন্য ব্যবহৃত হয়, যেখানে একটি বস্তুর অবস্থা অন্য নির্ভরশীল বস্তুতে ট্রিগার অ্যাকশন পরিবর্তন করে।
জাভাস্ক্রিপ্টে, আপনি কাস্টম ক্লাস বা বিল্ট-ইন বৈশিষ্ট্য যেমন ইভেন্ট শ্রোতা এবং addEventListener
পদ্ধতি ব্যবহার করে অবজারভার প্যাটার্ন প্রয়োগ করতে পারেন। ব্যবহারিক উদাহরণ সহ জাভাস্ক্রিপ্টে পর্যবেক্ষক প্যাটার্ন কীভাবে প্রয়োগ এবং ব্যবহার করা যায় তা অন্বেষণ করা যাক।
ধরুন আপনি একটি আবহাওয়া অ্যাপ্লিকেশন তৈরি করছেন, এবং আবহাওয়ার অবস্থার পরিবর্তন হলে আপনি UI এর বিভিন্ন অংশ আপডেট করতে চান। আপনি পর্যবেক্ষক প্যাটার্নের একটি কাস্টম বাস্তবায়ন ব্যবহার করতে পারেন:
class WeatherStation { constructor() { this.observers = []; }
addObserver(observer) { this.observers.push(observer); } removeObserver(observer) { const index = this.observers.indexOf(observer); if (index !== -1) { this.observers.splice(index, 1); } } notifyObservers() { this.observers.forEach((observer) => { observer.update(this); }); } setWeatherData(weatherData) { this.weatherData = weatherData; this.notifyObservers(); } }class WeatherDisplay { update(weatherStation) { console.log(`Current weather: ${weatherStation.weatherData}`); } }// Usage const weatherStation = new WeatherStation(); const display1 = new WeatherDisplay(); const display2 = new WeatherDisplay();weatherStation.addObserver(display1); weatherStation.addObserver(display2);weatherStation.setWeatherData('Sunny'); // Both displays update with the new weather data
এই উদাহরণে, WeatherStation একটি বিষয় হিসাবে কাজ করে যা পর্যবেক্ষকদের (ডিসপ্লে অবজেক্ট) আবহাওয়ার ডেটা পরিবর্তন করার সময় অবহিত করে। পর্যবেক্ষকরা addObserver পদ্ধতি ব্যবহার করে বিষয়ের সদস্যতা নেন এবং পরিবর্তনের প্রতিক্রিয়া জানাতে আপডেট পদ্ধতি প্রয়োগ করেন।
জাভাস্ক্রিপ্ট ইভেন্ট শ্রোতাদের ব্যবহার করে অবজারভার প্যাটার্ন বাস্তবায়নের জন্য একটি অন্তর্নির্মিত উপায় প্রদান করে:
class NewsPublisher { constructor() { this.subscribers = []; }
subscribe(subscriber) { this.subscribers.push(subscriber); } unsubscribe(subscriber) { const index = this.subscribers.indexOf(subscriber); if (index !== -1) { this.subscribers.splice(index, 1); } } publishNews(news) { this.subscribers.forEach((subscriber) => { subscriber(news); }); } }// Usage const publisher = new NewsPublisher();const subscriber1 = (news) => { console.log(`Subscriber 1 received news: ${news}`); };const subscriber2 = (news) => { console.log(`Subscriber 2 received news: ${news}`); };publisher.subscribe(subscriber1); publisher.subscribe(subscriber2);publisher.publishNews('Breaking News: Important Announcement');
এই উদাহরণে, NewsPublisher বিষয় হিসাবে কাজ করে, এবং সাবস্ক্রাইব পদ্ধতি ব্যবহার করে গ্রাহক (ফাংশন) যোগ করা হয়। publishNews পদ্ধতি গ্রাহকদের খবরের সাথে তাদের ফাংশন আহ্বান করে অবহিত করে।
পর্যবেক্ষক প্যাটার্ন বিভিন্ন পরিস্থিতিতে মূল্যবান, সহ:
পর্যবেক্ষক প্যাটার্ন ব্যবহার করার সময়, নিম্নলিখিত বিবেচনা করুন:
কৌশল প্যাটার্ন হল একটি আচরণগত নকশা প্যাটার্ন যা আপনাকে বিনিময়যোগ্য অ্যালগরিদমগুলির একটি পরিবারকে সংজ্ঞায়িত করতে, প্রতিটিকে এনক্যাপসুলেট করতে এবং তাদের বিনিময়যোগ্য করে তুলতে দেয়৷ এটি ক্লায়েন্টদের রানটাইমে গতিশীলভাবে উপযুক্ত অ্যালগরিদম বেছে নিতে সক্ষম করে। এই প্যাটার্নটি অ্যালগরিদমের আচরণকে যে প্রেক্ষাপট ব্যবহার করে তা থেকে আলাদা করে নমনীয়তা এবং পুনঃব্যবহারযোগ্যতা প্রচার করে।
জাভাস্ক্রিপ্টে, আপনি বিভিন্ন কৌশল এবং একটি প্রসঙ্গ অবজেক্ট উপস্থাপন করতে অবজেক্ট বা ফাংশন ব্যবহার করে কৌশল প্যাটার্ন বাস্তবায়ন করতে পারেন যা এই কৌশলগুলির মধ্যে পরিবর্তন করতে পারে। ব্যবহারিক উদাহরণ সহ জাভাস্ক্রিপ্টে স্ট্র্যাটেজি প্যাটার্ন কীভাবে বাস্তবায়ন এবং ব্যবহার করা যায় তা অন্বেষণ করা যাক।
ধরুন আপনি একটি ই-কমার্স অ্যাপ্লিকেশন তৈরি করছেন এবং আপনি বিভিন্ন ধরনের গ্রাহকদের জন্য ডিসকাউন্ট গণনা করতে চান। আপনি ডিসকাউন্ট কৌশল এনক্যাপসুলেট করতে কৌশল প্যাটার্ন ব্যবহার করতে পারেন:
// Discount Strategies const regularCustomerDiscount = (amount) => amount * 0.1; // 10% discount const premiumCustomerDiscount = (amount) => amount * 0.2; // 20% discount
// Context class ShoppingCart { constructor(discountStrategy) { this.items = []; this.discountStrategy = discountStrategy; } addItem(item) { this.items.push(item); } calculateTotal() { const subtotal = this.items.reduce((total, item) => total + item.price, 0); return subtotal - this.discountStrategy(subtotal); } }// Usage const regularCustomerCart = new ShoppingCart(regularCustomerDiscount); const premiumCustomerCart = new ShoppingCart(premiumCustomerDiscount);regularCustomerCart.addItem({ name: 'Item 1', price: 50 }); premiumCustomerCart.addItem({ name: 'Item 2', price: 100 });console.log(`Regular Customer Total: $${regularCustomerCart.calculateTotal()}`); // Output: $45 (after 10% discount) console.log(`Premium Customer Total: $${premiumCustomerCart.calculateTotal()}`); // Output: $80 (after 20% discount)
এই উদাহরণে, আমরা ফাংশন হিসাবে দুটি ডিসকাউন্ট কৌশল সংজ্ঞায়িত করি (নিয়মিত গ্রাহক ডিসকাউন্ট এবং প্রিমিয়াম কাস্টমার ডিসকাউন্ট)। শপিংকার্ট ক্লাস একটি ডিসকাউন্ট কৌশল একটি প্যারামিটার হিসাবে নেয় এবং নির্বাচিত কৌশলের উপর ভিত্তি করে মোট মূল্য গণনা করে।
কৌশল প্যাটার্ন বিভিন্ন পরিস্থিতিতে মূল্যবান, সহ:
কৌশল প্যাটার্ন ব্যবহার করার সময়, নিম্নলিখিত বিবেচনা করুন:
কমান্ড প্যাটার্ন হল একটি আচরণগত নকশা প্যাটার্ন যা একটি অনুরোধ বা সাধারণ অপারেশনকে একটি স্বতন্ত্র বস্তুতে পরিণত করে। এটি আপনাকে বিভিন্ন অনুরোধের সাথে অবজেক্টের প্যারামিটারাইজ করতে, অনুরোধের সম্পাদনে বিলম্ব বা সারিবদ্ধ করতে এবং অপরিবর্তনীয় ক্রিয়াকলাপগুলিকে সমর্থন করতে দেয়। এই প্যাটার্নটি তার রিসিভারের কাছ থেকে একটি অনুরোধের প্রেরককে দ্বিগুণ করে, এটি কোড প্রসারিত এবং বজায় রাখা সহজ করে তোলে।
জাভাস্ক্রিপ্টে, আপনি কমান্ড প্যাটার্ন প্রয়োগ করতে পারেন অবজেক্ট বা ক্লাস ব্যবহার করে কমান্ড এবং ইনভোকারদের প্রতিনিধিত্ব করতে যা সেই কমান্ডগুলি চালায়। আসুন ব্যবহারিক উদাহরণ সহ জাভাস্ক্রিপ্টে কমান্ড প্যাটার্ন কীভাবে প্রয়োগ এবং ব্যবহার করা যায় তা অন্বেষণ করি।
ধরুন আপনি একটি স্মার্ট হোমের জন্য একটি রিমোট কন্ট্রোল অ্যাপ্লিকেশন তৈরি করছেন এবং আপনি বিভিন্ন ডিভাইস নিয়ন্ত্রণ করার জন্য একটি নমনীয় উপায় তৈরি করতে চান।
আপনি কমান্ড প্যাটার্ন ব্যবহার করতে পারেন:
// Command interface class Command { execute() {} }
// Concrete Commands class LightOnCommand extends Command { constructor(light) { super(); this.light = light; } execute() { this.light.turnOn(); } }class LightOffCommand extends Command { constructor(light) { super(); this.light = light; } execute() { this.light.turnOff(); } }// Receiver (Device) class Light { turnOn() { console.log('Light is on.'); } turnOff() { console.log('Light is off.'); } }// Invoker (Remote Control) class RemoteControl { constructor() { this.commands = []; } addCommand(command) { this.commands.push(command); } executeCommands() { this.commands.forEach((command) => { command.execute(); }); } }// Usage const livingRoomLight = new Light(); const kitchenLight = new Light();const livingRoomLightOn = new LightOnCommand(livingRoomLight); const livingRoomLightOff = new LightOffCommand(livingRoomLight); const kitchenLightOn = new LightOnCommand(kitchenLight); const kitchenLightOff = new LightOffCommand(kitchenLight);const remoteControl = new RemoteControl();remoteControl.addCommand(livingRoomLightOn); remoteControl.addCommand(kitchenLightOff);remoteControl.executeCommands(); // Output: "Light is on." (for living room) // Output: "Light is off." (for kitchen)
এই উদাহরণে, কমান্ড প্যাটার্নটি লাইট চালু এবং বন্ধ করার ক্রিয়াগুলিকে এনক্যাপসুলেট করতে ব্যবহৃত হয়। রিমোট কন্ট্রোল আমন্ত্রণকারী হিসাবে কাজ করে এবং কংক্রিট কমান্ডগুলি (যেমন, LightOnCommand এবং LightOffCommand) কার্যকর করা ক্রিয়াগুলিকে এনক্যাপসুলেট করে৷
কমান্ড প্যাটার্ন বিভিন্ন পরিস্থিতিতে মূল্যবান, সহ:
কমান্ড প্যাটার্ন ব্যবহার করার সময়, নিম্নলিখিত বিবেচনা করুন:
স্টেট প্যাটার্ন হল একটি আচরণগত নকশা প্যাটার্ন যা একটি বস্তুর অভ্যন্তরীণ অবস্থার পরিবর্তন হলে তার আচরণ পরিবর্তন করতে দেয়। এটি রাজ্যগুলিকে পৃথক শ্রেণী হিসাবে অন্তর্ভুক্ত করে এবং বর্তমান অবস্থার অবজেক্টে আচরণ অর্পণ করে। এই প্যাটার্নটি জটিল অবস্থার ট্রানজিশন পরিচালনা করতে সাহায্য করে এবং "ওপেন-ক্লোজড" নীতির প্রচার করে, বিদ্যমান কোড পরিবর্তন না করেই নতুন রাজ্য যোগ করা সহজ করে তোলে।
জাভাস্ক্রিপ্টে, আপনি রাজ্যের প্রতিনিধিত্ব করার জন্য ক্লাস ব্যবহার করে স্টেট প্যাটার্ন বাস্তবায়ন করতে পারেন এবং একটি প্রসঙ্গ অবজেক্ট যা তার আচরণকে বর্তমান অবস্থায় অর্পণ করে। ব্যবহারিক উদাহরণ সহ জাভাস্ক্রিপ্টে স্টেট প্যাটার্ন কীভাবে প্রয়োগ এবং ব্যবহার করা যায় তা অন্বেষণ করা যাক।
ধরুন আপনি একটি ভেন্ডিং মেশিন তৈরি করছেন যা বিভিন্ন পণ্য সরবরাহ করে। ভেন্ডিং মেশিনের আচরণ তার বর্তমান অবস্থার উপর নির্ভর করে, যেমন "রেডি", "ডিসপেনসিং" বা "সোল্ড আউট"। আপনি এই আচরণের মডেল করতে রাজ্য প্যাটার্ন ব্যবহার করতে পারেন:
// State interface class VendingMachineState { insertMoney() {} ejectMoney() {} selectProduct() {} dispenseProduct() {} }
// Concrete States class ReadyState extends VendingMachineState { constructor(machine) { super(); this.machine = machine; } insertMoney() { console.log('Money inserted.'); this.machine.setState(this.machine.getDispensingState()); } selectProduct() { console.log('Please insert money first.'); } }class DispensingState extends VendingMachineState { constructor(machine) { super(); this.machine = machine; } dispenseProduct() { console.log('Product dispensed.'); this.machine.setState(this.machine.getReadyState()); } }class VendingMachine { constructor() { this.readyState = new ReadyState(this); this.dispensingState = new DispensingState(this); this.currentState = this.readyState; } setState(state) { this.currentState = state; } getReadyState() { return this.readyState; } getDispensingState() { return this.dispensingState; } insertMoney() { this.currentState.insertMoney(); } selectProduct() { this.currentState.selectProduct(); } dispenseProduct() { this.currentState.dispenseProduct(); } }// Usage const vendingMachine = new VendingMachine();vendingMachine.selectProduct(); // Output: "Please insert money first." vendingMachine.insertMoney(); // Output: "Money inserted." vendingMachine.dispenseProduct(); // Output: "Product dispensed."
এই উদাহরণে, স্টেট প্যাটার্ন একটি ভেন্ডিং মেশিনের আচরণ পরিচালনা করতে ব্যবহৃত হয়। "রেডি" এবং "ডিসপেনসিং" এর মতো রাজ্যগুলিকে আলাদা শ্রেণী হিসাবে উপস্থাপন করা হয় এবং প্রসঙ্গ (ভেন্ডিং মেশিন) বর্তমান অবস্থার সাথে তার আচরণকে অর্পণ করে।
রাজ্যের প্যাটার্ন বিভিন্ন পরিস্থিতিতে মূল্যবান, যার মধ্যে রয়েছে:
রাজ্য প্যাটার্ন ব্যবহার করার সময়, নিম্নলিখিত বিবেচনা করুন:
চেইন অফ রেসপনসিবিলিটি প্যাটার্ন হল একটি আচরণগত ডিজাইন প্যাটার্ন যা আপনাকে একটি অনুরোধ পরিচালনা করার জন্য বস্তুর একটি চেইন তৈরি করতে সাহায্য করে। চেইনের প্রতিটি বস্তুর অনুরোধটি প্রক্রিয়া করার বা চেইনের পরবর্তী অবজেক্টে পাঠানোর সুযোগ রয়েছে। এটি তার রিসিভার থেকে একটি অনুরোধের প্রেরককে দ্বিগুণ করে এবং একাধিক হ্যান্ডলারকে চেইনে থাকতে দেয়। এই প্যাটার্নটি আপনাকে ক্লায়েন্ট কোডকে প্রভাবিত না করে হ্যান্ডলারদের যোগ বা পরিবর্তন করতে সক্ষম করে নমনীয়তা এবং প্রসারণযোগ্যতা প্রচার করে।
জাভাস্ক্রিপ্টে, আপনি হ্যান্ডলারদের প্রতিনিধিত্ব করে এমন বস্তু বা ক্লাস ব্যবহার করে চেইন অফ রেসপনসিবিলিটি প্যাটার্ন প্রয়োগ করতে পারেন এবং অনুরোধ শুরু করে এমন একটি ক্লায়েন্ট। প্রতিটি হ্যান্ডলারের চেইনের পরবর্তী হ্যান্ডলারের একটি রেফারেন্স রয়েছে। আসুন ব্যবহারিক উদাহরণ সহ জাভাস্ক্রিপ্টে চেইন অফ রেসপন্সিবিলিটি প্যাটার্ন কীভাবে প্রয়োগ এবং ব্যবহার করা যায় তা অন্বেষণ করি।
ধরুন আপনি একটি অর্ডার প্রসেসিং সিস্টেম তৈরি করছেন এবং আপনি তাদের মোট পরিমাণের উপর ভিত্তি করে অর্ডারগুলি পরিচালনা করতে চান। আপনি হ্যান্ডলারদের একটি চেইন তৈরি করতে চেইন অফ রেসপনসিবিলিটি প্যাটার্ন ব্যবহার করতে পারেন, প্রতিটি একটি নির্দিষ্ট মূল্য সীমার মধ্যে অর্ডার প্রক্রিয়াকরণের জন্য দায়ী:
// Handler interface class OrderHandler { constructor() { this.nextHandler = null; }
setNextHandler(handler) { this.nextHandler = handler; } handleOrder(order) { if (this.canHandleOrder(order)) { this.processOrder(order); } else if (this.nextHandler) { this.nextHandler.handleOrder(order); } else { console.log('No handler can process this order.'); } } canHandleOrder(order) {} processOrder(order) {} }// Concrete Handlers class SmallOrderHandler extends OrderHandler { canHandleOrder(order) { return order.amount <= 100; } processOrder(order) { console.log(`Processing small order for ${order.amount}`); } }class MediumOrderHandler extends OrderHandler { canHandleOrder(order) { return order.amount <= 500; } processOrder(order) { console.log(`Processing medium order for ${order.amount}`); } }class LargeOrderHandler extends OrderHandler { canHandleOrder(order) { return order.amount > 500; } processOrder(order) { console.log(`Processing large order for ${order.amount}`); } }// Client class Order { constructor(amount) { this.amount = amount; } }// Usage const smallOrderHandler = new SmallOrderHandler(); const mediumOrderHandler = new MediumOrderHandler(); const largeOrderHandler = new LargeOrderHandler();smallOrderHandler.setNextHandler(mediumOrderHandler); mediumOrderHandler.setNextHandler(largeOrderHandler);const order1 = new Order(80); const order2 = new Order(250); const order3 = new Order(600);smallOrderHandler.handleOrder(order1); // Output: "Processing small order for 80" smallOrderHandler.handleOrder(order2); // Output: "Processing medium order for 250" smallOrderHandler.handleOrder(order3); // Output: "Processing large order for 600"
এই উদাহরণে, চেইন অফ রেসপনসিবিলিটি প্যাটার্নটি বিভিন্ন পরিমাণের অর্ডার পরিচালনা করতে ব্যবহৃত হয়। SmallOrderHandler, MediumOrderHandler এবং LargeOrderHandler-এর মতো হ্যান্ডলাররা প্রত্যেকেই অর্ডারের পরিমাণের উপর ভিত্তি করে অর্ডার প্রক্রিয়া করতে পারবে কিনা তা নির্ধারণ করে। যদি তারা পারে, তারা এটি প্রক্রিয়া করে; অন্যথায়, তারা চেইনের পরবর্তী হ্যান্ডলারের কাছে অর্ডারটি পাস করে।
চেইন অফ রেসপনসিবিলিটি প্যাটার্ন বিভিন্ন পরিস্থিতিতে মূল্যবান, যার মধ্যে রয়েছে:
চেইন অফ রেসপনসিবিলিটি প্যাটার্ন ব্যবহার করার সময়, নিম্নলিখিতগুলি বিবেচনা করুন:
ভিজিটর প্যাটার্ন হল একটি আচরণগত নকশার প্যাটার্ন যা আপনাকে এটি যে অবজেক্ট স্ট্রাকচারে কাজ করে তার থেকে একটি অ্যালগরিদমকে আলাদা করতে দেয়। এটি তাদের ক্লাস পরিবর্তন না করে অবজেক্টে নতুন ক্রিয়াকলাপ যোগ করার একটি উপায় প্রদান করে, জটিল অবজেক্ট শ্রেণীবিন্যাসগুলির জন্য কার্যকারিতা প্রসারিত করা সহজ করে তোলে। এই প্যাটার্নটি বিশেষভাবে উপযোগী যখন আপনার কাছে স্বতন্ত্র উপাদানগুলির একটি সেট থাকে এবং তাদের কোড পরিবর্তন না করেই তাদের উপর বিভিন্ন অপারেশন করতে চান।
জাভাস্ক্রিপ্টে, আপনি একটি অবজেক্ট স্ট্রাকচারের মধ্যে উপাদানগুলি দেখার জন্য দর্শকদের প্রতিনিধিত্ব করতে ফাংশন বা ক্লাস ব্যবহার করে ভিজিটর প্যাটার্ন প্রয়োগ করতে পারেন। আসুন ব্যবহারিক উদাহরণ সহ জাভাস্ক্রিপ্টে ভিজিটর প্যাটার্ন কীভাবে প্রয়োগ এবং ব্যবহার করা যায় তা অন্বেষণ করি।
ধরুন আপনি একটি কন্টেন্ট ম্যানেজমেন্ট সিস্টেম ডেভেলপ করছেন যেখানে আপনার বিভিন্ন ধরনের বিষয়বস্তু উপাদান যেমন নিবন্ধ, ছবি এবং ভিডিও রয়েছে। আপনি তাদের ক্লাস পরিবর্তন না করে এই উপাদানগুলিতে রেন্ডারিং এবং এক্সপোর্ট করার মতো বিভিন্ন ক্রিয়াকলাপ সম্পাদন করতে চান। আপনি ভিজিটর প্যাটার্ন ব্যবহার করতে পারেন:
// Element interface class ContentElement { accept(visitor) {} }
// Concrete Elements class Article extends ContentElement { accept(visitor) { visitor.visitArticle(this); } }class Image extends ContentElement { accept(visitor) { visitor.visitImage(this); } }class Video extends ContentElement { accept(visitor) { visitor.visitVideo(this); } }// Visitor interface class Visitor { visitArticle(article) {} visitImage(image) {} visitVideo(video) {} }// Concrete Visitors class RendererVisitor extends Visitor { visitArticle(article) { console.log(`Rendering article: ${article.title}`); } visitImage(image) { console.log(`Rendering image: ${image.caption}`); } visitVideo(video) { console.log(`Rendering video: ${video.title}`); } }class ExportVisitor extends Visitor { visitArticle(article) { console.log(`Exporting article: ${article.title}`); } visitImage(image) { console.log(`Exporting image: ${image.caption}`); } visitVideo(video) { console.log(`Exporting video: ${video.title}`); } }// Usage const elements = [new Article('Article 1'), new Image('Image 1'), new Video('Video 1')]; const renderer = new RendererVisitor(); const exporter = new ExportVisitor();elements.forEach((element) => { element.accept(renderer); element.accept(exporter); });
এই উদাহরণে, আমাদের কাছে নিবন্ধ, চিত্র এবং ভিডিওর মতো বিষয়বস্তু উপাদান রয়েছে এবং আমরা তাদের ক্লাস পরিবর্তন না করে রেন্ডারিং এবং রপ্তানি ক্রিয়াকলাপ করতে চাই৷ আমরা RendererVisitor এবং ExportVisitor এর মতো ভিজিটর ক্লাসগুলি বাস্তবায়ন করে এটি অর্জন করি যা উপাদানগুলি পরিদর্শন করে এবং পছন্দসই ক্রিয়াকলাপগুলি সম্পাদন করে৷
ভিজিটর প্যাটার্নটি বিভিন্ন পরিস্থিতিতে মূল্যবান, যার মধ্যে রয়েছে:
ভিজিটর প্যাটার্ন ব্যবহার করার সময়, নিম্নলিখিতগুলি বিবেচনা করুন:
জাভাস্ক্রিপ্টে ডিজাইন প্যাটার্নের এই ব্যাপক অন্বেষণে, আমরা বিভিন্ন প্যাটার্নের সন্ধান করেছি যা বিকাশকারীদের নমনীয়, রক্ষণাবেক্ষণযোগ্য এবং দক্ষ কোড তৈরি করতে সক্ষম করে। প্রতিটি ডিজাইন প্যাটার্ন নির্দিষ্ট সমস্যার সমাধান করে এবং সাধারণ সফ্টওয়্যার ডিজাইন চ্যালেঞ্জের মার্জিত সমাধান প্রদান করে।
আমরা ডিজাইন প্যাটার্নের মৌলিক ধারণা বোঝার মাধ্যমে শুরু করেছি এবং সেগুলিকে তিনটি প্রধান গ্রুপে শ্রেণীবদ্ধ করেছি: সৃষ্টিগত, কাঠামোগত এবং আচরণগত নিদর্শন। প্রতিটি বিভাগের মধ্যে, আমরা জনপ্রিয় ডিজাইনের প্যাটার্ন পরীক্ষা করেছি এবং জাভাস্ক্রিপ্টে তাদের ব্যবহারিক বাস্তবায়ন প্রদর্শন করেছি।
এখানে আমরা কভার করা মূল নকশার নিদর্শনগুলির একটি সংক্ষিপ্ত বিবরণ দেওয়া হল:
ক্রিয়েশনাল প্যাটার্নস: এই প্যাটার্নগুলি অবজেক্ট তৈরির মেকানিজমের উপর ফোকাস করে, যার মধ্যে একটি ক্লাসের একক ইন্সট্যান্স নিশ্চিত করার জন্য সিঙ্গেলটন প্যাটার্ন, নমনীয় ফ্যাক্টরি দিয়ে অবজেক্ট তৈরির জন্য ফ্যাক্টরি এবং অ্যাবস্ট্রাক্ট ফ্যাক্টরি প্যাটার্ন, ধাপে ধাপে জটিল বস্তু তৈরির জন্য বিল্ডার প্যাটার্ন, ক্লোনিংয়ের জন্য প্রোটোটাইপ প্যাটার্ন। বস্তু, এবং দক্ষ বস্তু পুনঃব্যবহারের জন্য অবজেক্ট পুল প্যাটার্ন।
স্ট্রাকচারাল প্যাটার্নস: এই প্যাটার্নগুলি বস্তুর গঠন নিয়ে কাজ করে, সহজ উপাদান থেকে জটিল কাঠামো তৈরি করার উপায় প্রদান করে। আমরা ইন্টারফেসগুলিকে অভিযোজিত করার জন্য অ্যাডাপ্টারের প্যাটার্ন, গতিশীলভাবে বস্তুতে আচরণ যোগ করার জন্য ডেকোরেটর প্যাটার্ন, বস্তুগুলিতে অ্যাক্সেস নিয়ন্ত্রণ করার জন্য প্রক্সি প্যাটার্ন, গাছের কাঠামোতে বস্তু রচনা করার জন্য যৌগিক প্যাটার্ন, বাস্তবায়ন থেকে বিমূর্ততাকে আলাদা করার জন্য সেতু প্যাটার্ন এবং ফ্লাইওয়েট অনুসন্ধান করেছি। সাধারণ অবস্থা ভাগ করে মেমরি ব্যবহার কমানোর জন্য প্যাটার্ন।
আচরণগত নিদর্শন: এই নিদর্শনগুলি বস্তুর মধ্যে মিথস্ক্রিয়া এবং যোগাযোগের সাথে সম্পর্কিত। আমরা ডিস্ট্রিবিউটেড ইভেন্ট হ্যান্ডলিং সিস্টেম বাস্তবায়নের জন্য পর্যবেক্ষক প্যাটার্ন, বিনিময়যোগ্য অ্যালগরিদমগুলিকে এনক্যাপসুলেট করার কৌশল প্যাটার্ন, অনুরোধগুলিকে স্বতন্ত্র বস্তুতে পরিণত করার জন্য কমান্ড প্যাটার্ন, অভ্যন্তরীণ অবস্থার উপর ভিত্তি করে অবজেক্ট আচরণ পরিচালনার জন্য রাষ্ট্রীয় প্যাটার্ন, একটি নির্মাণের জন্য চেইন অফ রেসপনসিবিলিটি প্যাটার্ন অন্তর্ভুক্ত করেছি। অনুরোধ প্রক্রিয়াকরণের জন্য হ্যান্ডলারের চেইন এবং অবজেক্ট স্ট্রাকচার থেকে অ্যালগরিদম আলাদা করার জন্য ভিজিটর প্যাটার্ন।
ডিজাইন প্যাটার্নগুলি একটি বিকাশকারীর টুলকিটে মূল্যবান সরঞ্জাম, যা পরিমাপযোগ্য এবং রক্ষণাবেক্ষণযোগ্য কোডবেস তৈরি করতে সক্ষম করে। আপনার জাভাস্ক্রিপ্ট প্রকল্পগুলিতে এই প্যাটার্নগুলি বোঝা এবং প্রয়োগ করা আপনাকে আরও দক্ষ, অভিযোজিত এবং শক্তিশালী সফ্টওয়্যার লিখতে দেয়।
মনে রাখবেন যে ডিজাইনের প্যাটার্নগুলি এক-আকার-ফিট-সমস্ত সমাধান নয়, এবং তাদের প্রযোজ্যতা আপনার প্রকল্পের নির্দিষ্ট প্রয়োজনীয়তা এবং চ্যালেঞ্জগুলির উপর নির্ভর করে। সর্বোত্তম ফলাফল অর্জনের জন্য কখন এবং কীভাবে এগুলি প্রয়োগ করতে হবে তা সাবধানতার সাথে বিবেচনা করুন।
আপনি যখন জাভাস্ক্রিপ্ট বিকাশকারী হিসাবে ক্রমাগত বৃদ্ধি পাচ্ছেন, এই ডিজাইন প্যাটার্নগুলি আয়ত্ত করা আপনাকে আত্মবিশ্বাস এবং সৃজনশীলতার সাথে জটিল সফ্টওয়্যার ডিজাইন চ্যালেঞ্জ মোকাবেলা করার ক্ষমতা দেবে৷ আপনি ওয়েব অ্যাপ্লিকেশন, গেম ইঞ্জিন বা অন্য কোনো সফ্টওয়্যার তৈরি করছেন না কেন, মার্জিত এবং রক্ষণাবেক্ষণযোগ্য কোড তৈরিতে ডিজাইনের প্যাটার্ন আপনার সহযোগী হবে। শুভ কোডিং!
এছাড়াও এখানে প্রকাশিত.