বিল্ডার প্যাটার্ন ব্যবহারের কয়েকটি সাধারণ , বাস্তব বিশ্বের উদাহরণ কী কী ? এটি আপনাকে কী কিনে দেয়? কেন শুধু কারখানার প্যাটার্ন ব্যবহার করবেন না?
বিল্ডার প্যাটার্ন ব্যবহারের কয়েকটি সাধারণ , বাস্তব বিশ্বের উদাহরণ কী কী ? এটি আপনাকে কী কিনে দেয়? কেন শুধু কারখানার প্যাটার্ন ব্যবহার করবেন না?
উত্তর:
একজন বিল্ডার এবং কারখানা আইএমএইচও-র মধ্যে মূল পার্থক্যটি হ'ল কোনও অবজেক্ট তৈরির জন্য যখন আপনাকে প্রচুর জিনিস করার দরকার হয় তখন একজন বিল্ডার দরকারী is উদাহরণস্বরূপ একটি ডিওএম কল্পনা করুন। আপনার চূড়ান্ত অবজেক্টটি পেতে আপনাকে প্রচুর নোড এবং বৈশিষ্ট্য তৈরি করতে হবে। একটি কারখানা ব্যবহৃত হয় যখন কারখানা সহজেই একটি পদ্ধতি কলের মধ্যে পুরো অবজেক্টটি তৈরি করতে পারে।
বিল্ডার ব্যবহারের একটি উদাহরণ হ'ল একটি এক্সএমএল ডকুমেন্ট তৈরি করা, আমি এই মডেলটি ব্যবহার করেছি যখন এইচটিএমএল টুকরো তৈরি করার সময় উদাহরণস্বরূপ আমার কাছে কোনও নির্দিষ্ট ধরণের টেবিল তৈরির জন্য একজন বিল্ডার থাকতে পারে এবং এটিতে নিম্নলিখিত পদ্ধতিগুলি থাকতে পারে (প্যারামিটারগুলি দেখানো হয় না) :
BuildOrderHeaderRow()
BuildLineItemSubHeaderRow()
BuildOrderRow()
BuildLineItemSubRow()
এই বিল্ডারটি তখন আমার জন্য এইচটিএমএল ছিটিয়ে দেবে। এটি একটি বৃহত পদ্ধতিগত পদ্ধতিতে চলার চেয়ে পড়া সহজ।
নীচে জাভাতে প্যাটার্ন এবং উদাহরণ কোডটি ব্যবহার করার জন্য তর্ক করছেন তবে এটি গ্যাং অফ ফোর ডিজাইন প্যাটার্নস দ্বারা আচ্ছাদিত বিল্ডার প্যাটার্নের একটি বাস্তবায়ন । আপনি এটি জাভাতে ব্যবহার করার কারণগুলি অন্যান্য প্রোগ্রামিং ভাষার ক্ষেত্রেও প্রযোজ্য।
জোশুয়া ব্লচ যেমন কার্যকর জাভাতে লিখেছেন , দ্বিতীয় সংস্করণ :
এমন ক্লাসগুলি ডিজাইন করার সময় বিল্ডার প্যাটার্নটি একটি ভাল পছন্দ যাঁর নির্মাণকারী বা স্থির কারখানাগুলি মুষ্টিমেয় প্যারামিটারের চেয়ে বেশি থাকে।
আমরা সবসময় কোনও এক সময়ে নির্মাণকারীর তালিকার সাথে একটি শ্রেণীর মুখোমুখি হয়েছি যেখানে প্রতিটি সংযোজন একটি নতুন বিকল্প পরামিতি যুক্ত করে:
Pizza(int size) { ... }
Pizza(int size, boolean cheese) { ... }
Pizza(int size, boolean cheese, boolean pepperoni) { ... }
Pizza(int size, boolean cheese, boolean pepperoni, boolean bacon) { ... }
একে টেলিস্কোপিং কনস্ট্রাক্টর প্যাটার্ন বলা হয়। এই প্যাটার্নটির সমস্যাটি হ'ল একবার কনস্ট্রাক্টর 4 বা 5 পরামিতি দীর্ঘ হলে প্যারামিটারগুলির প্রয়োজনীয় ক্রম এবং সেই সাথে আপনি কোন নির্দিষ্ট নির্মাতাকে কোনও নির্দিষ্ট পরিস্থিতিতে কী চাইবেন তা মনে রাখা দুষ্কর হয়ে পড়ে ।
আপনার কাছে টেলিस्कोপিং কনস্ট্রাক্টর প্যাটার্নের একটি বিকল্প জাভাবিয়ান প্যাটার্ন যেখানে আপনি বাধ্যতামূলক পরামিতিগুলির সাথে কোনও কনস্ট্রাক্টরকে কল করেন এবং তার পরে যেকোন alচ্ছিক সেটটারগুলিতে কল করুন:
Pizza pizza = new Pizza(12);
pizza.setCheese(true);
pizza.setPepperoni(true);
pizza.setBacon(true);
এখানে সমস্যাটি হ'ল কারণ বস্তুটি বেশ কয়েকটি কলগুলিতে তৈরি হয়েছিল এটি নির্মাণের মাধ্যমে পার্টওয়েতে এটি একটি বেমানান অবস্থায় থাকতে পারে। থ্রেড সুরক্ষা নিশ্চিত করতে এটির জন্য অতিরিক্ত অতিরিক্ত প্রচেষ্টাও প্রয়োজন requires
আরও ভাল বিকল্প হ'ল বিল্ডার প্যাটার্নটি ব্যবহার করা।
public class Pizza {
private int size;
private boolean cheese;
private boolean pepperoni;
private boolean bacon;
public static class Builder {
//required
private final int size;
//optional
private boolean cheese = false;
private boolean pepperoni = false;
private boolean bacon = false;
public Builder(int size) {
this.size = size;
}
public Builder cheese(boolean value) {
cheese = value;
return this;
}
public Builder pepperoni(boolean value) {
pepperoni = value;
return this;
}
public Builder bacon(boolean value) {
bacon = value;
return this;
}
public Pizza build() {
return new Pizza(this);
}
}
private Pizza(Builder builder) {
size = builder.size;
cheese = builder.cheese;
pepperoni = builder.pepperoni;
bacon = builder.bacon;
}
}
দ্রষ্টব্য যে পিজ্জা অপরিবর্তনীয় এবং প্যারামিটার মানগুলি একক স্থানে রয়েছে । কারণ বিল্ডারের সেটার পদ্ধতিগুলি বেড অবজেক্টকে তারা বেঁধে রাখতে সক্ষম করে দেয় ।
Pizza pizza = new Pizza.Builder(12)
.cheese(true)
.pepperoni(true)
.bacon(true)
.build();
কোডে এটি ফলাফল যা সহজেই লিখতে সহজ এবং পড়তে এবং বুঝতে খুব সহজ understand এই উদাহরণে, বিল্ডার থেকে পিজা অবজেক্টে অনুলিপি করার পরে পরামিতিগুলি পরীক্ষা করার জন্য বিল্ড পদ্ধতিটি পরিবর্তন করা যেতে পারে এবং যদি কোনও অবৈধ প্যারামিটার মান সরবরাহ করা হয় তবে একটি অবৈধ স্টেটএক্সপশন নিক্ষেপ করতে পারে । এই প্যাটার্নটি নমনীয় এবং ভবিষ্যতে এটিতে আরও পরামিতি যুক্ত করা সহজ। আপনি যদি কোনও নির্মাণকারীর জন্য 4 বা 5 টির বেশি পরামিতি রাখেন তবে এটি সত্যিই কার্যকর। এটি বলেছিল, ভবিষ্যতে আপনি আরও পরামিতি যুক্ত করতে পারেন বলে সন্দেহ করলে এটি প্রথম স্থানে সার্থক হতে পারে ।
আমি জোশুয়া ব্লচের দ্বিতীয় জাতির ইফেক্টিভ জাভা বইটি থেকে এই বিষয়টিতে প্রচুর bণ নিয়েছি । এই প্যাটার্ন এবং জাভা সম্পর্কিত অন্যান্য কার্যকর পদ্ধতি সম্পর্কে আরও জানার জন্য আমি এটির সুপারিশ করছি।
new Pizza.Builder(12).cheese().pepperoni().bacon().build();
Pizza.Builder(12).cheese().pepperoni().bacon().build();
করতে হবে বা আপনার যদি কেবল কিছু পেপারনি প্রয়োজন হয় পিজা। খুব কমপক্ষে আপনাকে @ কমিক্যাজে ভাড়াটে মূলত প্রস্তাবিত মত প্যারামিট্রাইজড সংস্করণও সরবরাহ করা উচিত। Pizza.Builder(12).cheese(true).pepperoni(false).bacon(false).build();
। তারপরে, আমরা কখনও ইউনিট-টেস্ট করি না, তাই না?
একটি রেস্তোঁরা বিবেচনা করুন। "আজকের খাবার" তৈরি করা একটি কারখানার প্যাটার্ন, কারণ আপনি রান্নাঘরটি "আমাকে আজকের খাবার পান" বলুন এবং রান্নাঘর (কারখানা) গোপনীয় মানদণ্ডের ভিত্তিতে কোন বস্তু উত্পন্ন করার সিদ্ধান্ত নেয়।
আপনি কাস্টম পিজ্জা অর্ডার করলে বিল্ডার উপস্থিত হয় appears এই ক্ষেত্রে ওয়েটার শেফকে (বিল্ডারকে) বলেন "আমার একটি পিজ্জা দরকার; এতে পনির, পেঁয়াজ এবং বেকন যুক্ত করুন!" সুতরাং, নির্মাতা উত্পন্ন বস্তুর থাকা বৈশিষ্ট্যগুলি প্রকাশ করে তবে কীভাবে সেট করতে হয় তা গোপন করে।
.NET স্ট্রিংবিল্ডার ক্লাস বিল্ডার প্যাটার্নের দুর্দান্ত উদাহরণ। এটি বেশিরভাগ ধাপে একটি স্ট্রিং তৈরি করতে ব্যবহৃত হয়। টোস্ট্রিং () করার চূড়ান্ত ফলাফলটি সর্বদা একটি স্ট্রিং তবে স্ট্রিংবিল্ডার শ্রেণিতে কোন ফাংশন ব্যবহৃত হত তার অনুসারে সেই স্ট্রিংটির সৃষ্টি পরিবর্তিত হয়। সংক্ষেপে বলতে গেলে, মূল ধারণাটি জটিল অবজেক্ট তৈরি করা এবং এটি কীভাবে নির্মিত হচ্ছে তার বাস্তবায়ন বিশদটি গোপন করা।
b.append(...).append(...)
শেষ পর্যন্ত কল করার আগে কেউ চেইন করতে পারে toString()
। উদ্ধৃতি: infoq.com/articles/internal-dsls-java
বহু-থ্রেডযুক্ত সমস্যার জন্য আমাদের প্রতিটি থ্রেডের জন্য একটি জটিল অবজেক্ট তৈরি করা দরকার। বস্তুটি ডেটা প্রক্রিয়াজাতকরণের প্রতিনিধিত্ব করে এবং ব্যবহারকারীর ইনপুটের উপর নির্ভর করে পরিবর্তিত হতে পারে।
পরিবর্তে আমরা একটি কারখানা ব্যবহার করতে পারি? হ্যাঁ
আমরা কেন করিনি? বিল্ডার আরও অনুভূত করে আমার অনুমান।
কারখানাগুলি বিভিন্ন ধরণের অবজেক্ট তৈরি করতে ব্যবহৃত হয় যা একই মৌলিক ধরণের (একই ইন্টারফেস বা বেস শ্রেণি বাস্তবায়ন করে)।
বিল্ডাররা একই ধরণের অবজেক্টকে বারবার তৈরি করে তবে নির্মাণটি গতিশীল তাই রানটাইম এ এটি পরিবর্তন করা যায়।
যখন আপনার কাছে ডিল করার প্রচুর বিকল্প থাকে আপনি এটি ব্যবহার করেন। জেমকের মতো জিনিসগুলি সম্পর্কে চিন্তা করুন:
m.expects(once())
.method("testMethod")
.with(eq(1), eq(2))
.returns("someResponse");
এটি অনেক বেশি প্রাকৃতিক বোধ করে এবং এটি সম্ভব possible
এখানে এক্সএমএল বিল্ডিং, স্ট্রিং বিল্ডিং এবং অন্যান্য অনেকগুলি জিনিস রয়েছে। ভেবে দেখুন java.util.Map
কোনও বিল্ডার হিসাবে রেখেছিলেন কিনা । আপনি এই জাতীয় জিনিস করতে পারেন:
Map<String, Integer> m = new HashMap<String, Integer>()
.put("a", 1)
.put("b", 2)
.put("c", 3);
মাইক্রোসফ্ট এমভিসি কাঠামো পেরিয়ে যাওয়ার সময় আমি বিল্ডার প্যাটার্ন সম্পর্কে চিন্তাভাবনা পেয়েছিলাম। আমি কন্ট্রোলার বিল্ডার ক্লাসে প্যাটার্নটি পেরিয়ে এসেছি। এই শ্রেণিটি নিয়ামক কারখানার ক্লাসটি ফিরিয়ে আনতে হয়, যা পরে কংক্রিট নিয়ামক তৈরি করতে ব্যবহৃত হয়।
বিল্ডার প্যাটার্নটি ব্যবহার করার ক্ষেত্রে আমি যে সুবিধাটি দেখছি তা হ'ল, আপনি নিজের একটি কারখানা তৈরি করতে পারেন এবং এটিকে ফ্রেমওয়ার্কে প্লাগ করতে পারেন।
@ তিথা, ইতালিয়ান রেস্তোরাঁ দ্বারা চালিত একটি রেস্তোঁরা (ফ্রেমওয়ার্ক) থাকতে পারে, যা পিজ্জা পরিবেশন করে। পিজ্জা প্রস্তুত করার জন্য ইতালীয় লোক (অবজেক্ট বিল্ডার) পিজ্জা বেস (বেস ক্লাস) সহ ওভেন (কারখানা) ব্যবহার করে।
এখন ভারতীয় লোক রেস্তোরাঁটি ইতালিয়ান লোকের কাছ থেকে নিয়ে যায়। পিজ্জার পরিবর্তে ভারতীয় রেস্তোঁরা (ফ্রেমওয়ার্ক) সার্ভারগুলি ডোসা। দোশা প্রস্তুত করার জন্য ভারতীয় লোক (অবজেক্ট বিল্ডার) মাইডা (বেস ক্লাস) দিয়ে ফ্রাইং প্যান (কারখানা) ব্যবহার করে
আপনি যদি দৃশ্যের দিকে নজর দেন তবে খাবারটি আলাদা, খাবার প্রস্তুত করার পদ্ধতিটি ভিন্ন, তবে একই রেস্তোঁরায় (একই কাঠামোর অধীনে)। রেস্তোঁরাগুলিকে এমনভাবে তৈরি করা উচিত যাতে এটি চীনা, মেক্সিকান বা যে কোনও খাবারের সমর্থন করতে পারে। ফ্রেমওয়ার্কের মধ্যে অবজেক্ট বিল্ডার আপনার পছন্দ মতো রান্না প্লাগিন করতে সহায়তা করে। উদাহরণ স্বরূপ
class RestaurantObjectBuilder
{
IFactory _factory = new DefaultFoodFactory();
//This can be used when you want to plugin the
public void SetFoodFactory(IFactory customFactory)
{
_factory = customFactory;
}
public IFactory GetFoodFactory()
{
return _factory;
}
}
আমি সর্বদা বিল্ডার প্যাটার্নটিকে অস্বাস্থ্যকর, বিঘ্নযুক্ত এবং খুব কম অভিজ্ঞ প্রোগ্রামারদের দ্বারা প্রায়শই অপব্যবহার করা হিসাবে অপছন্দ করি। এটি এমন একটি প্যাটার্ন যা কেবল তখনই বোধগম্য হয় যখন আপনাকে কিছু ডেটা থেকে অবজেক্টটি একত্রিত করতে হবে যার জন্য উত্তর-পরবর্তী পদক্ষেপের প্রয়োজন (যেমন একবার সমস্ত ডেটা সংগ্রহ করা হয় - এটি দিয়ে কিছু করুন)। পরিবর্তে, 99% সময় নির্মাতারা কেবল শ্রেণীর সদস্যদের সূচনা করার জন্য ব্যবহৃত হয়।
এই জাতীয় ক্ষেত্রে এটি কেবল ঘোষণা করা আরও ভাল withXyz(...)
শ্রেণীর অভ্যন্তরে টাইপ সেটারগুলি এবং তাদের নিজের কাছে একটি রেফারেন্স ফিরিয়ে দেওয়া আরও অনেক ভাল।
এই বিবেচনা:
public class Complex {
private String first;
private String second;
private String third;
public String getFirst(){
return first;
}
public void setFirst(String first){
this.first=first;
}
...
public Complex withFirst(String first){
this.first=first;
return this;
}
public Complex withSecond(String second){
this.second=second;
return this;
}
public Complex withThird(String third){
this.third=third;
return this;
}
}
Complex complex = new Complex()
.withFirst("first value")
.withSecond("second value")
.withThird("third value");
এখন আমাদের একটি ঝরঝরে সিঙ্গেল ক্লাস রয়েছে যা তার নিজস্ব ইনিশিয়েশন পরিচালনা করে এবং বিল্ডারের মতো প্রায় একই কাজটি করে, এর চেয়ে আরও মার্জিত except
বিল্ডারের আর একটি সুবিধা হ'ল যদি আপনার কোনও কারখানা থাকে তবে আপনার কোডে এখনও কিছু সংযুক্তি রয়েছে, কারণ কারখানার কাজ করার জন্য, এটি সম্ভবত তৈরি করতে পারে এমন সমস্ত বস্তু জানতে হবে । যদি আপনি তৈরি হতে পারে এমন কোনও অন্য বস্তু যুক্ত করেন তবে তাকে অন্তর্ভুক্ত করতে আপনাকে কারখানার শ্রেণিটি সংশোধন করতে হবে। এটি অ্যাবস্ট্রাক্ট ফ্যাক্টরিতেও ঘটে।
অন্যদিকে, বিল্ডারের সাথে, আপনাকে এই নতুন শ্রেণীর জন্য একটি নতুন কংক্রিট বিল্ডার তৈরি করতে হবে। ডিরেক্টর ক্লাসটি একই থাকবে, কারণ এটি নির্মাত্রে বিল্ডারকে গ্রহণ করে।
এছাড়াও, বিল্ডারের অনেক স্বাদ রয়েছে। কামিকাজে ভাড়াটে আরেকটি উপহার দেয়।
/// <summary>
/// Builder
/// </summary>
public interface IWebRequestBuilder
{
IWebRequestBuilder BuildHost(string host);
IWebRequestBuilder BuildPort(int port);
IWebRequestBuilder BuildPath(string path);
IWebRequestBuilder BuildQuery(string query);
IWebRequestBuilder BuildScheme(string scheme);
IWebRequestBuilder BuildTimeout(int timeout);
WebRequest Build();
}
/// <summary>
/// ConcreteBuilder #1
/// </summary>
public class HttpWebRequestBuilder : IWebRequestBuilder
{
private string _host;
private string _path = string.Empty;
private string _query = string.Empty;
private string _scheme = "http";
private int _port = 80;
private int _timeout = -1;
public IWebRequestBuilder BuildHost(string host)
{
_host = host;
return this;
}
public IWebRequestBuilder BuildPort(int port)
{
_port = port;
return this;
}
public IWebRequestBuilder BuildPath(string path)
{
_path = path;
return this;
}
public IWebRequestBuilder BuildQuery(string query)
{
_query = query;
return this;
}
public IWebRequestBuilder BuildScheme(string scheme)
{
_scheme = scheme;
return this;
}
public IWebRequestBuilder BuildTimeout(int timeout)
{
_timeout = timeout;
return this;
}
protected virtual void BeforeBuild(HttpWebRequest httpWebRequest) {
}
public WebRequest Build()
{
var uri = _scheme + "://" + _host + ":" + _port + "/" + _path + "?" + _query;
var httpWebRequest = WebRequest.CreateHttp(uri);
httpWebRequest.Timeout = _timeout;
BeforeBuild(httpWebRequest);
return httpWebRequest;
}
}
/// <summary>
/// ConcreteBuilder #2
/// </summary>
public class ProxyHttpWebRequestBuilder : HttpWebRequestBuilder
{
private string _proxy = null;
public ProxyHttpWebRequestBuilder(string proxy)
{
_proxy = proxy;
}
protected override void BeforeBuild(HttpWebRequest httpWebRequest)
{
httpWebRequest.Proxy = new WebProxy(_proxy);
}
}
/// <summary>
/// Director
/// </summary>
public class SearchRequest
{
private IWebRequestBuilder _requestBuilder;
public SearchRequest(IWebRequestBuilder requestBuilder)
{
_requestBuilder = requestBuilder;
}
public WebRequest Construct(string searchQuery)
{
return _requestBuilder
.BuildHost("ajax.googleapis.com")
.BuildPort(80)
.BuildPath("ajax/services/search/web")
.BuildQuery("v=1.0&q=" + HttpUtility.UrlEncode(searchQuery))
.BuildScheme("http")
.BuildTimeout(-1)
.Build();
}
public string GetResults(string searchQuery) {
var request = Construct(searchQuery);
var resp = request.GetResponse();
using (StreamReader stream = new StreamReader(resp.GetResponseStream()))
{
return stream.ReadToEnd();
}
}
}
class Program
{
/// <summary>
/// Inside both requests the same SearchRequest.Construct(string) method is used.
/// But finally different HttpWebRequest objects are built.
/// </summary>
static void Main(string[] args)
{
var request1 = new SearchRequest(new HttpWebRequestBuilder());
var results1 = request1.GetResults("IBM");
Console.WriteLine(results1);
var request2 = new SearchRequest(new ProxyHttpWebRequestBuilder("localhost:80"));
var results2 = request2.GetResults("IBM");
Console.WriteLine(results2);
}
}
পূর্ববর্তী উত্তরের উপর ভিত্তি করে (পাং উদ্দেশ্যে), একটি দুর্দান্ত বাস্তব-বিশ্বের উদাহরণ গ্রোভির সমর্থনে নির্মিত Builders
।
MarkupBuilder
StreamingMarkupBuilder
SwingXBuilder
দেখুন বিল্ডার্স মধ্যে খাঁজকাটা ডকুমেন্টেশন
আমি গৃহ-প্রাপ্ত ম্যাসেজিং লাইব্রেরিতে বিল্ডার ব্যবহার করেছি। লাইব্রেরি কোরটি তার থেকে ডেটা গ্রহণ করছিল, এটি বিল্ডারের উদাহরণ সহ সংগ্রহ করল, তারপরে, একবার বিল্ডার সিদ্ধান্ত নিলেন যে বার্তা উদাহরণ তৈরি করার জন্য এটি প্রয়োজনীয় সমস্ত কিছু পেয়েছে, বিল্ডার G গেটমেসেজ () এর কাছ থেকে সংগৃহীত ডেটা ব্যবহার করে একটি বার্তা তৈরি করছিল টেলিগ্রাম।
ইনারবিল্ডারটি দেখুন, একটি ইন্টেলিজ আইডিইএ প্লাগইন যা জেনারেট মেনুতে একটি 'বিল্ডার' ক্রিয়া যুক্ত করে (Alt + Insert) যা কার্যকর জাভাতে বর্ণিত একটি অভ্যন্তরীণ বিল্ডার শ্রেণি তৈরি করে
আমি যখন জাভাতে ডেটটাইম মার্শালিংয়ের আপত্তি জানাতে আমার এক্সএমএলের জন্য স্ট্যান্ডার্ড এক্সএমএল গ্রেগরিয়ানক্যালেন্ডারটি ব্যবহার করতে চেয়েছিলাম, তখন এটি ব্যবহার করা কত ভারী ওজন এবং জটিল ছিল তা নিয়ে আমি প্রচুর মন্তব্য শুনেছি। আমি এক্সএসএমএল এক্সএমএল ক্ষেত্রগুলিকে কন্ট্রোল করার চেষ্টা করছিলাম: টাইমজোন, মিলিসেকেন্ডস ইত্যাদি পরিচালনা করার জন্য ডেটটাইম স্ট্রাক্ট
সুতরাং আমি একটি গ্রেগরিয়ানক্যালেন্ডার বা জাভা.ইটিল.ডেট থেকে এক্সএমএল গ্রেগরিয়ান ক্যালেন্ডার তৈরি করার জন্য একটি ইউটিলিটি ডিজাইন করেছি।
আমি যেখানে কাজ করি সে কারণে আমাকে আইনী ছাড়া অনলাইনে ভাগ করার অনুমতি দেওয়া হচ্ছে না, তবে ক্লায়েন্ট কীভাবে এটি ব্যবহার করে তার উদাহরণ এখানে। এটি বিশদ বিমূর্ত করে এবং এক্সএমএল গ্রেগরিয়ানক্যালেন্ডার প্রয়োগের কিছু ফিল্টার করে যা এক্স এর জন্য কম ব্যবহৃত হয়: ডেটটাইম।
XMLGregorianCalendarBuilder builder = XMLGregorianCalendarBuilder.newInstance(jdkDate);
XMLGregorianCalendar xmlCalendar = builder.excludeMillis().excludeOffset().build();
অনুমোদিত যে এই প্যাটার্নটি আরও বেশি ফিল্টার হিসাবে এটি এক্সএমএলক্যালেন্ডারে ক্ষেত্রগুলি নির্ধারিত হিসাবে সেট করে যাতে তারা বাদ যায় না, এটি এখনও এটি "তৈরি করে"। আমি একটি এক্স, তারিখ এবং এক্সএস: টাইম স্ট্রাক্ট তৈরি করতে এবং প্রয়োজনের সময় টাইমজোন অফসেটগুলি পরিচালনা করতে সহজেই বিল্ডারের সাথে অন্যান্য বিকল্প যুক্ত করেছি।
আপনি যদি কখনও এমন কোড দেখে থাকেন যা XMLGregorianC ক্যালেন্ডার তৈরি করে এবং ব্যবহার করে তবে আপনি দেখতে পাবেন যে এটি কীভাবে ম্যানিপুলেট করা সহজ করেছে।
আপনার ক্লাস পরীক্ষার সময় ইউনিট ব্যবহার করার জন্য একটি দুর্দান্ত বাস্তব বিশ্বের উদাহরণ। আপনি সট (সিস্টেমের অধীনে টেস্ট) বিল্ডার ব্যবহার করেন।
উদাহরণ:
ক্লাস:
public class CustomAuthenticationService
{
private ICloudService _cloudService;
private IDatabaseService _databaseService;
public CustomAuthenticationService(ICloudService cloudService, IDatabaseService databaseService)
{
_cloudService = cloudService;
_databaseService = databaseService;
}
public bool IsAuthorized(User user)
{
//Implementation Details
return true;
}
টেস্ট:
[Test]
public void Given_a_User_With_Permission_When_Verifying_If_Authorized_Then_Authorize_It_Returning_True()
{
CustomAuthenticationService sut = new CustomAuthenticationServiceBuilder();
User userWithAuthorization = null;
var result = sut.IsAuthorized(userWithAuthorization);
Assert.That(result, Is.True);
}
সট নির্মাতা:
public class CustomAuthenticationServiceBuilder
{
private ICloudService _cloudService;
private IDatabaseService _databaseService;
public CustomAuthenticationServiceBuilder()
{
_cloudService = new AwsService();
_databaseService = new SqlServerService();
}
public CustomAuthenticationServiceBuilder WithAzureService(AzureService azureService)
{
_cloudService = azureService;
return this;
}
public CustomAuthenticationServiceBuilder WithOracleService(OracleService oracleService)
{
_databaseService = oracleService;
return this;
}
public CustomAuthenticationService Build()
{
return new CustomAuthenticationService(_cloudService, _databaseService);
}
public static implicit operator CustomAuthenticationService (CustomAuthenticationServiceBuilder builder)
{
return builder.Build();
}
}
CustomAuthenticationService
ক্লাসে কেবল সেটটার যুক্ত করার পরিবর্তে আপনার কেন এই ক্ষেত্রে একজন বিল্ডারের প্রয়োজন হবে ?