Builder — একটি সৃষ্টিমূলক প্যাটার্ন যা জটিল অবজেক্ট ধাপে ধাপে তৈরি করতে দেয়। ডজনখানেক প্যারামিটারযুক্ত কন্সট্রাক্টরের বিপরীতে, Builder কলের চেইনের মাধ্যমে অবজেক্ট একত্রিত করে, প্রতিটি একটি ফিল্ড কনফিগার করে। প্যাটার্নটি বিশেষ করে অনেক অপশনাল প্যারামিটারযুক্ত অবজেক্টের জন্য উপযোগী: নেটওয়ার্ক ক্লায়েন্ট কনফিগারেশন, ডেটাবেস সেটিংস, অ্যালার্ট এবং নেভিগেশন বিল্ডার। আরও জানতে Refactoring Guru: Builder দেখুন।
মূল পয়েন্ট
Builder — একটি সৃষ্টিমূলক GoF প্যাটার্ন যা জটিল অবজেক্টের নির্মাণকে তার উপস্থাপনা থেকে পৃথক করে। একই নির্মাণ প্রক্রিয়া ভিন্ন ভিন্ন উপস্থাপনা তৈরি করতে পারে। Builder তখন উপযোগী যখন একটি অবজেক্টের অনেক অপশনাল প্যারামিটার থাকে এবং দশটি ফিল্ডের কন্সট্রাক্টর অপাঠ্য এবং অনমনীয় হয়। প্যাটার্নটি Telescoping Constructor অ্যান্টি-প্যাটার্নও সমাধান করে, যেখানে কন্সট্রাক্টর ওভারলোডের সংখ্যা দ্রুতগতিতে বাড়ে।
Builder কাঠামো মূল ক্লাসের ফিল্ড প্রতিফলিত করে এমন ফিল্ডসহ একটি অভ্যন্তরীণ স্ট্যাটিক Builder ক্লাস অন্তর্ভুক্ত করে। প্রতিটি set-পদ্ধতি fluent chaining-এর জন্য Builder (this) রিটার্ন করে। চূড়ান্ত build() পদ্ধতি একটি প্রাইভেট কন্সট্রাক্টরে ফিল্ডের মান পাস করে লক্ষ্য অবজেক্ট তৈরি করে। মূল ক্লাসের একটি প্রাইভেট কন্সট্রাক্টর আছে যা Builder গ্রহণ করে। ক্লায়েন্ট: Object.builder().setField1(val1).setField2(val2).build().
কখন Builder ব্যবহার করবেন — 5+ ফিল্ডের অবজেক্ট যেখানে শুধু 2-3টি আবশ্যক। কনফিগারেশন অবজেক্ট (RequestConfig, DatabaseConfig)। নির্মাণের সময় জটিল বৈধতা যুক্তিযুক্ত অবজেক্ট। নির্মাণের পর যে অবজেক্ট অপরিবর্তনীয় (immutable) থাকতে হবে। Android-এ, Builder SDK-তে সক্রিয়ভাবে ব্যবহৃত হয়: AlertDialog.Builder, Retrofit.Builder, OkHttpClient.Builder, NotificationCompat.Builder.
Kotlin Builder-এর দুটি পদ্ধতি আছে: ক্লাসিক Java-শৈলী Builder (নেস্টেড ক্লাসের মাধ্যমে) এবং Kotlin-শৈলী DSL builder (রিসিভারসহ ল্যাম্বডার মাধ্যমে)। Java-শৈলী Builder Android সামঞ্জস্যতার জন্য এবং Java কোডের সাথে ব্যবহারে পছন্দনীয়। DSL builder হল Kotlin-এর স্বাভাবিক উপায়: একটি ফাংশন ল্যাম্বডা গ্রহণ করে যার ভিতরে this Builder প্রসঙ্গ যেখানে ফিল্ড সরাসরি নির্ধারণ করা যায়।
// ক্লাসিক Builder
data class HttpConfig private constructor(
val baseUrl: String,
val timeout: Long = 30_000,
val retries: Int = 3,
val headers: Map<String, String> = emptyMap()
) {
class Builder {
private var baseUrl: String = ""
private var timeout: Long = 30_000
private var retries: Int = 3
private var headers: MutableMap<String, String> = mutableMapOf()
fun baseUrl(url: String) = apply { this.baseUrl = url }
fun timeout(ms: Long) = apply { this.timeout = ms }
fun retries(n: Int) = apply { this.retries = n }
fun header(key: String, value: String) = apply { headers[key] = value }
fun build(): HttpConfig {
require(baseUrl.isNotBlank()) { "baseUrl is required" }
return HttpConfig(baseUrl, timeout, retries, headers)
}
}
}
// ব্যবহার
val config = HttpConfig.Builder()
.baseUrl("https://api.example.com")
.timeout(15_000)
.header("Authorization", "Bearer token")
.build()
Kotlin DSL builder — নেস্টেড ক্লাস ছাড়া একটি বিকল্প। একটি builder ফাংশন একটি বিল্ডার অবজেক্টের প্রসঙ্গে ল্যাম্বডা গ্রহণ করে। এটি Kotlin-এর জন্য স্বাভাবিক এবং write-ফিল্ডের প্রয়োজন হয় না। DSL builders Ktor Client, kotlinx.serialization, Compose (Modifier)-এ সক্রিয়ভাবে ব্যবহৃত হয়। DSL builder Java-এর সাথে সামঞ্জস্যপূর্ণ নয় এবং Java API-যুক্ত লাইব্রেরির জন্য উপযুক্ত নয়।
Swift Builder — Swift-এ বিল্ট-ইন Builder প্যাটার্ন নেই, তবে Self রিটার্নকারী পদ্ধতির মাধ্যমে fluent interface সহজেই বাস্তবায়িত হয়। প্রতিটি পদ্ধতি একটি প্রপার্টি কনফিগার করে এবং self রিটার্ন করে। Kotlin-এর বিপরীতে, Swift-এর আলাদা Builder ক্লাসের প্রয়োজন নেই — আপনি অবজেক্ট নিজেই রিটার্ন করতে পারেন যদি এটি অ্যাসেম্বলির সময় mutable হয়। অপরিবর্তনীয় অবজেক্টের জন্য, Kotlin-এর মতো একটি নেস্টেড Builder ক্লাস ব্যবহৃত হয়।
struct NetworkRequest {
let url: String
let method: HTTPMethod
let headers: [String: String]
let body: Data?
let timeout: TimeInterval
final class Builder {
private var url: String = ""
private var method: HTTPMethod = .get
private var headers: [String: String] = [:]
private var body: Data? = nil
private var timeout: TimeInterval = 30
func withURL(_: String) -> Self { /* self */ }
func withMethod(_: HTTPMethod) -> Self { /* self */ }
func withHeader(key: String, value: String) -> Self { /* self */ }
func withBody(_: Data) -> Self { /* self */ }
func withTimeout(_: TimeInterval) -> Self { /* self */ }
func build() throws -> NetworkRequest {
guard !url.isEmpty else { throw BuilderError.missingURL }
return NetworkRequest(
url: url, method: method, headers: headers,
body: body, timeout: timeout
)
}
}
}
Result Builders — Swift 5.4 @resultBuilder চালু করেছে — ঘোষণামূলক কাঠামো নির্মাণের জন্য একটি ভাষা প্রক্রিয়া। SwiftUI, AttributedString, SceneBuilder result builders ব্যবহার করে। এটি ক্লাসিক Builder-এর বিকল্প: set-পদ্ধতির চেইনের পরিবর্তে, result builder কোড ব্লক ব্যবহার করে যার উপাদান কম্পাইলার একটি অ্যারে বা ট্রিতে একত্রিত করে। SwiftUI-তে @ViewBuilder সবচেয়ে পরিচিত উদাহরণ: body-র ভিতরে if, switch, ForEach লেখা যায়, এবং কম্পাইলার শর্ত থেকে View তৈরি করে।
Telescoping Constructor — একটি অ্যান্টি-প্যাটার্ন যেখানে একটি ক্লাসের প্যারামিটারের ভিন্ন ভিন্ন সেটসহ অনেক ওভারলোডেড কন্সট্রাক্টর থাকে। উদাহরণস্বরূপ, তিনটি কন্সট্রাক্টর: HttpConfig(url), HttpConfig(url, timeout), HttpConfig(url, timeout, retries)। প্যারামিটার বাড়ার সাথে সাথে কন্সট্রাক্টরের সংখ্যা দ্রুতগতিতে বাড়ে — n অপশনাল ফিল্ডের জন্য n! কম্বিনেশন প্রয়োজন। Builder শুধু প্রয়োজনীয় ফিল্ড উল্লেখের অনুমতি দিয়ে এই সমস্যার সমাধান করে।
| বৈশিষ্ট্য | Telescoping Constructor | Builder | Kotlin named args |
|---|---|---|---|
| কোডের পরিমাণ | দ্রুতগতির বৃদ্ধি | রৈখিক বৃদ্ধি | সর্বনিম্ন |
| পাঠযোগ্যতা | কম (কোন প্যারামিটার কোনটি?) | উচ্চ (পদ্ধতি + নাম) | উচ্চ (নাম = মান) |
| অপরিবর্তনীয়তা | অপরিবর্তনীয় | অপরিবর্তনীয় | অপরিবর্তনীয় |
| Java সামঞ্জস্য | পূর্ণ | পূর্ণ | কোনোটিই নয় (শুধু Kotlin) |
| বৈধতা | প্রত্যেক কন্সট্রাক্টরে | build()-এ — একবার | init()-এ |
Kotlin named arguments + ডিফল্ট মান — বিশুদ্ধ Kotlin প্রজেক্টে Builder-এর একটি মার্জিত বিকল্প। কন্সট্রাক্টর প্যারামিটারের ডিফল্ট মান থাকে, ক্লায়েন্ট শুধু প্রয়োজনীয়গুলো পাস করে: HttpConfig(baseUrl = url, timeout = 15_000)। ত্রুটি হল কম্পাইল টাইমে আবশ্যক ফিল্ড যাচাই করতে অক্ষমতা। Builder Builder কন্সট্রাক্টরের মাধ্যমে আবশ্যক ফিল্ড প্রদান করে (baseUrl আবশ্যক)। Java লাইব্রেরির জন্য, Builder কার্যকরী মানক হিসেবে রয়ে গেছে।
Android SDK-এ Builder — স্ট্যান্ডার্ড লাইব্রেরিতে সবচেয়ে সাধারণ প্যাটার্নগুলির একটি। AlertDialog.Builder: new AlertDialog.Builder(context).setTitle().setMessage().setPositiveButton().create(). Retrofit.Builder: new Retrofit.Builder().baseUrl().addConverterFactory().build(). OkHttpClient.Builder: new OkHttpClient.Builder().connectTimeout().addInterceptor().build(). NotificationCompat.Builder: setContentTitle().setContentText().setSmallIcon().build().
কেন Google Builder ব্যবহার করে — পশ্চাৎগামী সামঞ্জস্য। Builder-এ নতুন পদ্ধতি যোগ করা বিদ্যমান কোড ভাঙে না। যদি Google ২০ প্যারামিটারের কন্সট্রাক্টর ব্যবহার করত, প্রতিটি নতুন ফিল্ডের জন্য নতুন ওভারলোড প্রয়োজন হতো। Builder বছরজুড়ে breaking changes ছাড়া set-পদ্ধতি যোগ করতে দেয়। উদাহরণস্বরূপ, NotificationCompat.Builder Android 11-এ setBubbleMetadata() যোগ করেছে, বিদ্যমান কোডকে প্রভাবিত না করে।
Kotlin লাইব্রেরিতে Builder — Ktor (HttpClientBuilder), Coil (ImageRequest.Builder), Room (Room.databaseBuilder(context, AppDatabase.class, "db").fallbackToDestructiveMigration().build()), Navigation (NavOptionsBuilder)। Kotlin প্রজেক্টে, Builder প্রায়ই DSL-এর সাথে মিলিত হয়: Room.databaseBuilder(context, AppDatabase.class, "db").fallbackToDestructiveMigration().build(). প্যাটার্নটি পাবলিক API-র জন্য প্রাসঙ্গিক রয়ে গেছে যেখানে পশ্চাৎগামী সামঞ্জস্য এবং Java ইন্টারঅপ গুরুত্বপূর্ণ।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
Builder 1-3 ফিল্ডের অবজেক্টের জন্য অপ্রয়োজনীয় — সাধারণ কন্সট্রাক্টর বা data class স্পষ্ট। Java ইন্টারঅপ ছাড়া Kotlin প্রজেক্টেও এটি অপ্রয়োজনীয়, যেখানে named arguments + ডিফল্ট মান একই কাজ আরও সহজে সমাধান করে। Builder 5+ ফিল্ড, জটিল বৈধতা বা Java API-র জন্য ন্যায়সঙ্গত যেখানে named arguments উপলব্ধ নয়।
Builder একটি জটিল অবজেক্ট ধাপে ধাপে তৈরি করে (ফিল্ড কনফিগারেশন), Factory টাইপ বা প্যারামিটার অনুসারে সম্পূর্ণ অবজেক্ট তৈরি করে। Builder প্রশ্ন «কীভাবে একত্রিত করবেন?»-এর উত্তর দেয়, Factory «কী তৈরি করবেন?»-এর। Builder প্রায়ই Factory-এর সাথে মিলিত হয়: Factory টাইপ নির্বাচন করে, Builder ফিল্ড কনফিগার করে।
SwiftUI-তে, Builder-এর ভূমিকা পালন করে result builders (@ViewBuilder, @SceneBuilder) এবং View পরিবর্তক (.font(), .padding())। ক্লাসিক Builder প্রয়োজন নেই কারণ SwiftUI ঘোষণামূলক পদ্ধতি এবং fluent modifiers ব্যবহার করে। UIKit উপাদানের জন্য, Builder উপযোগী: UIAlertController, URLRequest, NSAttributedString।
Builder সাধারণত থ্রেড নিরাপত্তার প্রয়োজন হয় না কারণ এটি একটি অবজেক্ট একত্রিত করতে একক থ্রেডে ব্যবহৃত হয়। যদি Builder মাল্টিথ্রেডেড পরিবেশে (বিরল ক্ষেত্রে) ব্যবহার করা হয়, প্রতিটি set-পদ্ধতি এবং build() সিঙ্ক্রোনাইজ করুন। বিকল্প — Immutable Builder: প্রতিটি set-পদ্ধতি পরিবর্তিত ফিল্ডসহ একটি নতুন Builder ইনস্ট্যান্স রিটার্ন করে।
Retrofit.Builder একটি পাবলিক লাইব্রেরি API যা DI কন্টেইনার ছাড়া কাজ করতে হবে। Builder Dagger বা অন্যান্য DI ফ্রেমওয়ার্কের উপর নির্ভরতা ছাড়া কনফিগারেশন নমনীয়তা (baseUrl, কনভার্টার, ইন্টারসেপ্টর, কাস্টম কল অ্যাডাপ্টার) প্রদান করে। একটি অ্যাপ্লিকেশনের ভিতরে, DI Builder-এর মাধ্যমে একবার Retrofit তৈরি করতে পারে, কিন্তু Builder নিজেই Retrofit-এর পাবলিক API-র অংশ রয়ে গেছে।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন