আপনি কখন বিল্ডার প্যাটার্নটি ব্যবহার করবেন? [বন্ধ]


530

বিল্ডার প্যাটার্ন ব্যবহারের কয়েকটি সাধারণ , বাস্তব বিশ্বের উদাহরণ কী কী ? এটি আপনাকে কী কিনে দেয়? কেন শুধু কারখানার প্যাটার্ন ব্যবহার করবেন না?


Stackoverflow.com/questions/35238292/... কিছু API গুলি উল্লেখ করেন যে, ব্যবহার রচয়িতা প্যাটার্ন
আলিরেজা Fattahi

হারুন এবং তিথার উত্তরগুলি সত্যই তথ্যবহুল। এই উত্তরগুলির সাথে সম্পর্কিত পুরো নিবন্ধটি এখানে ।
ডায়াবলো

উত্তর:


262

একজন বিল্ডার এবং কারখানা আইএমএইচও-র মধ্যে মূল পার্থক্যটি হ'ল কোনও অবজেক্ট তৈরির জন্য যখন আপনাকে প্রচুর জিনিস করার দরকার হয় তখন একজন বিল্ডার দরকারী is উদাহরণস্বরূপ একটি ডিওএম কল্পনা করুন। আপনার চূড়ান্ত অবজেক্টটি পেতে আপনাকে প্রচুর নোড এবং বৈশিষ্ট্য তৈরি করতে হবে। একটি কারখানা ব্যবহৃত হয় যখন কারখানা সহজেই একটি পদ্ধতি কলের মধ্যে পুরো অবজেক্টটি তৈরি করতে পারে।

বিল্ডার ব্যবহারের একটি উদাহরণ হ'ল একটি এক্সএমএল ডকুমেন্ট তৈরি করা, আমি এই মডেলটি ব্যবহার করেছি যখন এইচটিএমএল টুকরো তৈরি করার সময় উদাহরণস্বরূপ আমার কাছে কোনও নির্দিষ্ট ধরণের টেবিল তৈরির জন্য একজন বিল্ডার থাকতে পারে এবং এটিতে নিম্নলিখিত পদ্ধতিগুলি থাকতে পারে (প্যারামিটারগুলি দেখানো হয় না) :

BuildOrderHeaderRow()
BuildLineItemSubHeaderRow()
BuildOrderRow()
BuildLineItemSubRow()

এই বিল্ডারটি তখন আমার জন্য এইচটিএমএল ছিটিয়ে দেবে। এটি একটি বৃহত পদ্ধতিগত পদ্ধতিতে চলার চেয়ে পড়া সহজ।

উইকিপিডিয়ায় বিল্ডার প্যাটার্নটি দেখুন ।


1020

নীচে জাভাতে প্যাটার্ন এবং উদাহরণ কোডটি ব্যবহার করার জন্য তর্ক করছেন তবে এটি গ্যাং অফ ফোর ডিজাইন প্যাটার্নস দ্বারা আচ্ছাদিত বিল্ডার প্যাটার্নের একটি বাস্তবায়ন । আপনি এটি জাভাতে ব্যবহার করার কারণগুলি অন্যান্য প্রোগ্রামিং ভাষার ক্ষেত্রেও প্রযোজ্য।

জোশুয়া ব্লচ যেমন কার্যকর জাভাতে লিখেছেন , দ্বিতীয় সংস্করণ :

এমন ক্লাসগুলি ডিজাইন করার সময় বিল্ডার প্যাটার্নটি একটি ভাল পছন্দ যাঁর নির্মাণকারী বা স্থির কারখানাগুলি মুষ্টিমেয় প্যারামিটারের চেয়ে বেশি থাকে।

আমরা সবসময় কোনও এক সময়ে নির্মাণকারীর তালিকার সাথে একটি শ্রেণীর মুখোমুখি হয়েছি যেখানে প্রতিটি সংযোজন একটি নতুন বিকল্প পরামিতি যুক্ত করে:

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ণ নিয়েছি । এই প্যাটার্ন এবং জাভা সম্পর্কিত অন্যান্য কার্যকর পদ্ধতি সম্পর্কে আরও জানার জন্য আমি এটির সুপারিশ করছি।


24
মূল জিওএফ বিল্ডার থেকে আলাদা? কারণ এখানে কোনও ডিরেক্টর ক্লাস নেই। আমার কাছে প্রায় অন্য প্যাটার্নের মতো মনে হয় তবে আমি এটি খুব দরকারী বলে সম্মত।
লিনো রোজা 0

194
এই নির্দিষ্ট উদাহরণের জন্য, বুলিয়ান প্যারামিটারগুলি অপসারণ করা এবং এটি বলতে সক্ষম হবেন নাnew Pizza.Builder(12).cheese().pepperoni().bacon().build();
ফ্যাবিয়ান স্টেগ


21
@ ফ্যাবিয়ান স্টেগ, আমি মনে করি লোকেরা সুন্দর বুলিয়ান সেটারগুলির প্রতি অত্যধিক আচরণ করছে, মনে রাখবেন যে এই ধরণের সেটার রানটাইম পরিবর্তনের অনুমতি দেয় না:, আপনার কোডটি পুনরায় সংকলন Pizza.Builder(12).cheese().pepperoni().bacon().build();করতে হবে বা আপনার যদি কেবল কিছু পেপারনি প্রয়োজন হয় পিজা। খুব কমপক্ষে আপনাকে @ কমিক্যাজে ভাড়াটে মূলত প্রস্তাবিত মত প্যারামিট্রাইজড সংস্করণও সরবরাহ করা উচিত। Pizza.Builder(12).cheese(true).pepperoni(false).bacon(false).build();। তারপরে, আমরা কখনও ইউনিট-টেস্ট করি না, তাই না?
egallardo

23
@ জেসনসি রাইট, এবং যাইহোক একটি অপরিবর্তনীয় পিৎজা কি ব্যবহার?
মার্টেন বোদেউয়েস

325

একটি রেস্তোঁরা বিবেচনা করুন। "আজকের খাবার" তৈরি করা একটি কারখানার প্যাটার্ন, কারণ আপনি রান্নাঘরটি "আমাকে আজকের খাবার পান" বলুন এবং রান্নাঘর (কারখানা) গোপনীয় মানদণ্ডের ভিত্তিতে কোন বস্তু উত্পন্ন করার সিদ্ধান্ত নেয়।

আপনি কাস্টম পিজ্জা অর্ডার করলে বিল্ডার উপস্থিত হয় appears এই ক্ষেত্রে ওয়েটার শেফকে (বিল্ডারকে) বলেন "আমার একটি পিজ্জা দরকার; এতে পনির, পেঁয়াজ এবং বেকন যুক্ত করুন!" সুতরাং, নির্মাতা উত্পন্ন বস্তুর থাকা বৈশিষ্ট্যগুলি প্রকাশ করে তবে কীভাবে সেট করতে হয় তা গোপন করে।


নিতিন এই প্রশ্নের অন্য উত্তরে রান্নাঘরের উপমা বাড়িয়েছিলেন ।
পোপস

19

.NET স্ট্রিংবিল্ডার ক্লাস বিল্ডার প্যাটার্নের দুর্দান্ত উদাহরণ। এটি বেশিরভাগ ধাপে একটি স্ট্রিং তৈরি করতে ব্যবহৃত হয়। টোস্ট্রিং () করার চূড়ান্ত ফলাফলটি সর্বদা একটি স্ট্রিং তবে স্ট্রিংবিল্ডার শ্রেণিতে কোন ফাংশন ব্যবহৃত হত তার অনুসারে সেই স্ট্রিংটির সৃষ্টি পরিবর্তিত হয়। সংক্ষেপে বলতে গেলে, মূল ধারণাটি জটিল অবজেক্ট তৈরি করা এবং এটি কীভাবে নির্মিত হচ্ছে তার বাস্তবায়ন বিশদটি গোপন করা।


9
আমি মনে করি না যে এটি নির্মাতা প্যাটার্ন। স্ট্রিংবিল্ডার হ'ল একটি অক্ষর অ্যারে শ্রেণীর (যেমন স্ট্রিং) আরও একটি বাস্তবায়ন, তবে এটি কর্মক্ষমতা এবং মেমরির পরিচালনাটিকে অ্যাকাউন্টে তোলে, কারণ স্ট্রিংগুলি অবিচ্ছেদ্য।
চার্লস গ্রাহাম

23
এটি একেবারে বিল্ডার প্যাটার্ন, যেমন জাভার স্ট্রিংবিল্ডার ক্লাস। এই উভয় শ্রেণীর সংযোজন () পদ্ধতি স্ট্রিংবিল্ডার নিজেই কীভাবে ফিরে আসে তা লক্ষ করুন, যাতে b.append(...).append(...)শেষ পর্যন্ত কল করার আগে কেউ চেইন করতে পারে toString()। উদ্ধৃতি: infoq.com/articles/internal-dsls-java
Pohl

3
@ পোহল ইয়া আমি সত্যিই এটি একটি বিল্ডার প্যাটার্ন মনে করি না, আমি বলব এটি কেবলমাত্র একটি সাবলীল ইন্টারফেস।
দিদিয়ার এ।

"লক্ষ্য করুন কীভাবে এই উভয় শ্রেণীর সংযোজন () পদ্ধতিটি স্ট্রিংবিল্ডার নিজেই ফিরিয়ে দেয়" বিল্ডার প্যাটার্নটিকে নয়, কেবল একটি সাবলীল ইন্টারফেসকে দেয়। এটি ঠিক যে প্রায়শই কোনও নির্মাতা একটি সাবলীল ইন্টারফেস ব্যবহার করতে পারে। একজন বিল্ডারের কাছে সাবলীল ইন্টারফেস থাকতে হবে না।
বাইটেদেভ

তবে মনে রাখবেন যে স্ট্রিংবুডার প্রকৃতি অনুসারে সিঙ্ক্রোনাইজ করা হয় না, স্ট্রিংবুফারের সাথে সিঙ্ক্রোনাইজ করা unlike
অ্যালান ডিপ

11

বহু-থ্রেডযুক্ত সমস্যার জন্য আমাদের প্রতিটি থ্রেডের জন্য একটি জটিল অবজেক্ট তৈরি করা দরকার। বস্তুটি ডেটা প্রক্রিয়াজাতকরণের প্রতিনিধিত্ব করে এবং ব্যবহারকারীর ইনপুটের উপর নির্ভর করে পরিবর্তিত হতে পারে।

পরিবর্তে আমরা একটি কারখানা ব্যবহার করতে পারি? হ্যাঁ

আমরা কেন করিনি? বিল্ডার আরও অনুভূত করে আমার অনুমান।

কারখানাগুলি বিভিন্ন ধরণের অবজেক্ট তৈরি করতে ব্যবহৃত হয় যা একই মৌলিক ধরণের (একই ইন্টারফেস বা বেস শ্রেণি বাস্তবায়ন করে)।

বিল্ডাররা একই ধরণের অবজেক্টকে বারবার তৈরি করে তবে নির্মাণটি গতিশীল তাই রানটাইম এ এটি পরিবর্তন করা যায়।


9

যখন আপনার কাছে ডিল করার প্রচুর বিকল্প থাকে আপনি এটি ব্যবহার করেন। জেমকের মতো জিনিসগুলি সম্পর্কে চিন্তা করুন:

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);

3
আমি "যদি" মানচিত্রটি একটি বিল্ডার প্যাটার্ন প্রয়োগ করে এবং সেখানে নির্মাণকাজটি দেখে অবাক হয়েছিলাম তা ভুলে গিয়েছিলাম .. :)
সেতু

3
:) এর জন্যে দুঃখিত. অকার্যকর পরিবর্তে স্ব-স্ব ফিরে আসা অনেক ভাষায় সাধারণ। আপনি এটি জাভাতে করতে পারেন, তবে এটি খুব সাধারণ নয়।
ডাস্টিন

7
মানচিত্রের উদাহরণটি কেবল পদ্ধতিতে শৃঙ্খলার একটি উদাহরণ।
নোগ্রিডবাগ

@ নোগ্রিডবাগ এটি আসলে পদ্ধতি ক্যাসকেডিংয়ের কাছাকাছি হবে। যদিও এটি এমনভাবে শৃঙ্খলা ব্যবহার করছে যা ক্যাসকেডিংয়ের অনুকরণ করে, তাই এটি অবশ্যই শিকল দিচ্ছে, তবে শব্দার্থগতভাবে এটি ক্যাসকেডিং হিসাবে আচরণ করে।
দিদিয়ার এ।

9

মাইক্রোসফ্ট এমভিসি কাঠামো পেরিয়ে যাওয়ার সময় আমি বিল্ডার প্যাটার্ন সম্পর্কে চিন্তাভাবনা পেয়েছিলাম। আমি কন্ট্রোলার বিল্ডার ক্লাসে প্যাটার্নটি পেরিয়ে এসেছি। এই শ্রেণিটি নিয়ামক কারখানার ক্লাসটি ফিরিয়ে আনতে হয়, যা পরে কংক্রিট নিয়ামক তৈরি করতে ব্যবহৃত হয়।

বিল্ডার প্যাটার্নটি ব্যবহার করার ক্ষেত্রে আমি যে সুবিধাটি দেখছি তা হ'ল, আপনি নিজের একটি কারখানা তৈরি করতে পারেন এবং এটিকে ফ্রেমওয়ার্কে প্লাগ করতে পারেন।

@ তিথা, ইতালিয়ান রেস্তোরাঁ দ্বারা চালিত একটি রেস্তোঁরা (ফ্রেমওয়ার্ক) থাকতে পারে, যা পিজ্জা পরিবেশন করে। পিজ্জা প্রস্তুত করার জন্য ইতালীয় লোক (অবজেক্ট বিল্ডার) পিজ্জা বেস (বেস ক্লাস) সহ ওভেন (কারখানা) ব্যবহার করে।

এখন ভারতীয় লোক রেস্তোরাঁটি ইতালিয়ান লোকের কাছ থেকে নিয়ে যায়। পিজ্জার পরিবর্তে ভারতীয় রেস্তোঁরা (ফ্রেমওয়ার্ক) সার্ভারগুলি ডোসা। দোশা প্রস্তুত করার জন্য ভারতীয় লোক (অবজেক্ট বিল্ডার) মাইডা (বেস ক্লাস) দিয়ে ফ্রাইং প্যান (কারখানা) ব্যবহার করে

আপনি যদি দৃশ্যের দিকে নজর দেন তবে খাবারটি আলাদা, খাবার প্রস্তুত করার পদ্ধতিটি ভিন্ন, তবে একই রেস্তোঁরায় (একই কাঠামোর অধীনে)। রেস্তোঁরাগুলিকে এমনভাবে তৈরি করা উচিত যাতে এটি চীনা, মেক্সিকান বা যে কোনও খাবারের সমর্থন করতে পারে। ফ্রেমওয়ার্কের মধ্যে অবজেক্ট বিল্ডার আপনার পছন্দ মতো রান্না প্লাগিন করতে সহায়তা করে। উদাহরণ স্বরূপ

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;
   }
}

7

আমি সর্বদা বিল্ডার প্যাটার্নটিকে অস্বাস্থ্যকর, বিঘ্নযুক্ত এবং খুব কম অভিজ্ঞ প্রোগ্রামারদের দ্বারা প্রায়শই অপব্যবহার করা হিসাবে অপছন্দ করি। এটি এমন একটি প্যাটার্ন যা কেবল তখনই বোধগম্য হয় যখন আপনাকে কিছু ডেটা থেকে অবজেক্টটি একত্রিত করতে হবে যার জন্য উত্তর-পরবর্তী পদক্ষেপের প্রয়োজন (যেমন একবার সমস্ত ডেটা সংগ্রহ করা হয় - এটি দিয়ে কিছু করুন)। পরিবর্তে, 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


আমি কেবল ঠিক করেছি যে আমি আমার জটিল এক্সএমএল ডকুমেন্টটিকে জেএসএন হিসাবে তৈরি করতে চাই। প্রথমত, আমি কীভাবে জানব যে ক্লাস 'কমপ্লেক্স' প্রথম স্থানে একটি এক্সএমএল পণ্য সরবরাহ করতে সক্ষম এবং আমি কীভাবে এটিকে JSONable অবজেক্ট তৈরি করতে পরিবর্তন করব? তাত্ক্ষণিক উত্তর: আমার পক্ষে বিল্ডার ব্যবহার করা দরকার বলে আমি পারছি না। এবং আমরা পুরো চেনাশোনাতে আসি ...
ডেভিড বার্কার

1
মোট বিএস, নির্মাতা অপরিবর্তনীয় অবজেক্টগুলি তৈরির জন্য ডিজাইন করা হয়েছে এবং দক্ষতার সাথে ভবিষ্যতে পণ্য শ্রেণীর স্পর্শ না করেই বিল্ডিংয়ের পদ্ধতি পরিবর্তন করে
মিকি টিন

6
Hmmm? আপনি কি উত্তরটি কোথাও পড়েছিলেন যা আমাকে বিল্ডারের জন্য ডিজাইন করা হয়েছে বলে বলে? এটি শীর্ষস্থানীয় প্রশ্নের বিকল্প দৃষ্টিভঙ্গি "আপনি কখন বিল্ডার প্যাটার্নটি ব্যবহার করবেন?", যা নিদর্শনটির অগণিত অপব্যবহারের অভিজ্ঞতার ভিত্তিতে তৈরি করা হয়েছে, যেখানে আরও সাধারণ কিছু কাজ আরও ভাল করে তোলে। কখন এবং কীভাবে সেগুলি ব্যবহার করতে হয় তা যদি আপনি জানেন তবে সমস্ত নিদর্শনগুলি কার্যকর - এটিই প্রথম স্থানে নিদর্শনগুলি ডকুমেন্ট করার সম্পূর্ণ পয়েন্ট! যখন প্যাটার্নটি অতিরিক্ত ব্যবহার করা হয় বা খারাপ হয় - অপব্যবহার করা হয় - তখন তা আপনার কোডের প্রসঙ্গে একটি অ্যান্টি-প্যাটার্ন হয়ে যায়। হায়রে ...
পাভেল লেচেভ

6

বিল্ডারের আর একটি সুবিধা হ'ল যদি আপনার কোনও কারখানা থাকে তবে আপনার কোডে এখনও কিছু সংযুক্তি রয়েছে, কারণ কারখানার কাজ করার জন্য, এটি সম্ভবত তৈরি করতে পারে এমন সমস্ত বস্তু জানতে হবে । যদি আপনি তৈরি হতে পারে এমন কোনও অন্য বস্তু যুক্ত করেন তবে তাকে অন্তর্ভুক্ত করতে আপনাকে কারখানার শ্রেণিটি সংশোধন করতে হবে। এটি অ্যাবস্ট্রাক্ট ফ্যাক্টরিতেও ঘটে।

অন্যদিকে, বিল্ডারের সাথে, আপনাকে এই নতুন শ্রেণীর জন্য একটি নতুন কংক্রিট বিল্ডার তৈরি করতে হবে। ডিরেক্টর ক্লাসটি একই থাকবে, কারণ এটি নির্মাত্রে বিল্ডারকে গ্রহণ করে।

এছাড়াও, বিল্ডারের অনেক স্বাদ রয়েছে। কামিকাজে ভাড়াটে আরেকটি উপহার দেয়।


6
/// <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);
    }
}

1
আপনি আপনার উত্তর দুটি উপায়ে উন্নত করতে পারেন: 1) এটি এসএসসিসিই করুন। 2) এটি কীভাবে প্রশ্নের উত্তর দেয় তা ব্যাখ্যা কর।
james.garriss

6

পূর্ববর্তী উত্তরের উপর ভিত্তি করে (পাং উদ্দেশ্যে), একটি দুর্দান্ত বাস্তব-বিশ্বের উদাহরণ গ্রোভির সমর্থনে নির্মিত Builders

দেখুন বিল্ডার্স মধ্যে খাঁজকাটা ডকুমেন্টেশন


3

আমি গৃহ-প্রাপ্ত ম্যাসেজিং লাইব্রেরিতে বিল্ডার ব্যবহার করেছি। লাইব্রেরি কোরটি তার থেকে ডেটা গ্রহণ করছিল, এটি বিল্ডারের উদাহরণ সহ সংগ্রহ করল, তারপরে, একবার বিল্ডার সিদ্ধান্ত নিলেন যে বার্তা উদাহরণ তৈরি করার জন্য এটি প্রয়োজনীয় সমস্ত কিছু পেয়েছে, বিল্ডার G গেটমেসেজ () এর কাছ থেকে সংগৃহীত ডেটা ব্যবহার করে একটি বার্তা তৈরি করছিল টেলিগ্রাম।


3

ইনারবিল্ডারটি দেখুন, একটি ইন্টেলিজ আইডিইএ প্লাগইন যা জেনারেট মেনুতে একটি 'বিল্ডার' ক্রিয়া যুক্ত করে (Alt + Insert) যা কার্যকর জাভাতে বর্ণিত একটি অভ্যন্তরীণ বিল্ডার শ্রেণি তৈরি করে

https://github.com/analytically/innerbuilder


2

আমি যখন জাভাতে ডেটটাইম মার্শালিংয়ের আপত্তি জানাতে আমার এক্সএমএলের জন্য স্ট্যান্ডার্ড এক্সএমএল গ্রেগরিয়ানক্যালেন্ডারটি ব্যবহার করতে চেয়েছিলাম, তখন এটি ব্যবহার করা কত ভারী ওজন এবং জটিল ছিল তা নিয়ে আমি প্রচুর মন্তব্য শুনেছি। আমি এক্সএসএমএল এক্সএমএল ক্ষেত্রগুলিকে কন্ট্রোল করার চেষ্টা করছিলাম: টাইমজোন, মিলিসেকেন্ডস ইত্যাদি পরিচালনা করার জন্য ডেটটাইম স্ট্রাক্ট

সুতরাং আমি একটি গ্রেগরিয়ানক্যালেন্ডার বা জাভা.ইটিল.ডেট থেকে এক্সএমএল গ্রেগরিয়ান ক্যালেন্ডার তৈরি করার জন্য একটি ইউটিলিটি ডিজাইন করেছি।

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

XMLGregorianCalendarBuilder builder = XMLGregorianCalendarBuilder.newInstance(jdkDate);
XMLGregorianCalendar xmlCalendar = builder.excludeMillis().excludeOffset().build();

অনুমোদিত যে এই প্যাটার্নটি আরও বেশি ফিল্টার হিসাবে এটি এক্সএমএলক্যালেন্ডারে ক্ষেত্রগুলি নির্ধারিত হিসাবে সেট করে যাতে তারা বাদ যায় না, এটি এখনও এটি "তৈরি করে"। আমি একটি এক্স, তারিখ এবং এক্সএস: টাইম স্ট্রাক্ট তৈরি করতে এবং প্রয়োজনের সময় টাইমজোন অফসেটগুলি পরিচালনা করতে সহজেই বিল্ডারের সাথে অন্যান্য বিকল্প যুক্ত করেছি।

আপনি যদি কখনও এমন কোড দেখে থাকেন যা XMLGregorianC ক্যালেন্ডার তৈরি করে এবং ব্যবহার করে তবে আপনি দেখতে পাবেন যে এটি কীভাবে ম্যানিপুলেট করা সহজ করেছে।


0

আপনার ক্লাস পরীক্ষার সময় ইউনিট ব্যবহার করার জন্য একটি দুর্দান্ত বাস্তব বিশ্বের উদাহরণ। আপনি সট (সিস্টেমের অধীনে টেস্ট) বিল্ডার ব্যবহার করেন।

উদাহরণ:

ক্লাস:

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ক্লাসে কেবল সেটটার যুক্ত করার পরিবর্তে আপনার কেন এই ক্ষেত্রে একজন বিল্ডারের প্রয়োজন হবে ?
লাউর ইভান

এটি একটি ভাল প্রশ্ন @ লাউরিয়ান! হতে পারে আমার উদাহরণটি কিছুটা দরিদ্র ছিল, তবে আপনি কাস্টমআউটথ্যান্টিকেশন সার্ভিস ক্লাসটি পরিবর্তন করতে পারবেন না তা কল্পনা করুন, বিল্ডারটি আপনার ইউনিট পরীক্ষার পাঠকে উন্নত করার জন্য একটি আকর্ষণীয় উপায় হবে। এবং আমি মনে করি তৈরিকারী এবং সেটটারগুলি আপনার ক্ষেত্রগুলি উন্মোচিত করবে, যা কেবলমাত্র আপনার পরীক্ষার জন্য ব্যবহৃত হবে। আপনি যদি সট বিল্ডার সম্পর্কে আরও কিছু জানতে চান তবে আপনি টেস্ট ডেটা বিল্ডার সম্পর্কে পড়তে পারেন , যা বেশ প্রায় একই, তবে স্যুটগুলির ক্ষেত্রে।
রাফায়েল মাইকেলি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.