কার্যকর জাভাতে বিল্ডার প্যাটার্ন


137

আমি সম্প্রতি জোশুয়া ব্লচের কার্যকর জাভা পড়া শুরু করেছি। আমি বিল্ডার প্যাটার্নের ধারণাটি পেয়েছি [বইয়ের 2 আইটেম] আকর্ষণীয়। আমি এটি আমার প্রকল্পে বাস্তবায়নের চেষ্টা করেছি তবে সংকলনের ত্রুটি ছিল। নীচে আমি যা করতে চেষ্টা করেছিলাম তা হল:

একাধিক বৈশিষ্ট্যযুক্ত এবং এর নির্মাতা শ্রেণীর সাথে শ্রেণি:

public class NutritionalFacts {
    private int sodium;
    private int fat;
    private int carbo;

    public class Builder {
        private int sodium;
        private int fat;
        private int carbo;

        public Builder(int s) {
            this.sodium = s;
        }

        public Builder fat(int f) {
            this.fat = f;
            return this;
        }

        public Builder carbo(int c) {
            this.carbo = c;
            return this;
        }

        public NutritionalFacts build() {
            return new NutritionalFacts(this);
        }
    }

    private NutritionalFacts(Builder b) {
        this.sodium = b.sodium;
        this.fat = b.fat;
        this.carbo = b.carbo;
    }
}

ক্লাস যেখানে আমি উপরের ক্লাসটি ব্যবহার করার চেষ্টা করি:

public class Main {
    public static void main(String args[]) {
        NutritionalFacts n = 
            new NutritionalFacts.Builder(10).carbo(23).fat(1).build();
    }
}

আমি নিম্নলিখিত সংকলক ত্রুটি পেয়েছি:

একটি সংলগ্ন উদাহরণ যা কার্যকরী জাভা.বিল্ডারপ্যাটার্ন.নুশনালফ্যাক্টস.বিল্ডার প্রয়োজনীয় পুষ্টি প্রয়োজন n = নতুন নিউট্রিশনাল ফ্যাক্স.বিল্ডার (10) .কার্বো (23) .ফ্যাট (1)। বিল্ড ();

বার্তাটির অর্থ কী তা আমি বুঝতে পারি না। দয়া করে ব্যাখ্যা করুন. উপরের কোডটি ব্লোক তার বইয়ের পরামর্শের উদাহরণের মতো।


উত্তর:


171

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

public class NutritionFacts {
    public static class Builder {
    }
}

রেফারেন্স: নেস্টেড ক্লাস


34
এবং, আসলে, Builderহয় staticবই (পৃষ্ঠা 14, 2nd সংস্করণ লাইন 10) মধ্যে উদাহরণে।
পাওয়ারলর্ড

27

আপনার বিল্ডার শ্রেণিটিকে স্থির হিসাবে তৈরি করা উচিত এবং ক্ষেত্রগুলি চূড়ান্ত করা উচিত এবং সেই মানগুলি পেতে গেটারদের থাকা উচিত। এই মানগুলিতে সেটটার সরবরাহ করবেন না। এইভাবে আপনার ক্লাস পুরোপুরি পরিবর্তনযোগ্য হবে।

public class NutritionalFacts {
    private final int sodium;
    private final int fat;
    private final int carbo;

    public int getSodium(){
        return sodium;
    }

    public int getFat(){
        return fat;
    }

    public int getCarbo(){
        return carbo;
    }

    public static class Builder {
        private int sodium;
        private int fat;
        private int carbo;

        public Builder sodium(int s) {
            this.sodium = s;
            return this;
        }

        public Builder fat(int f) {
            this.fat = f;
            return this;
        }

        public Builder carbo(int c) {
            this.carbo = c;
            return this;
        }

        public NutritionalFacts build() {
            return new NutritionalFacts(this);
        }
    }

    private NutritionalFacts(Builder b) {
        this.sodium = b.sodium;
        this.fat = b.fat;
        this.carbo = b.carbo;
    }
}

এবং এখন আপনি নীচের হিসাবে বৈশিষ্ট্য সেট করতে পারেন:

NutritionalFacts n = new NutritionalFacts.Builder().sodium(10).carbo(15).
fat(5).build();

কেন কেবল নিউট্রিশনাল ফ্যাক্টস ক্ষেত্রগুলি পাবলিক করবেন না? তারা ইতিমধ্যে চূড়ান্ত, এবং এটি এখনও অপরিবর্তনীয় হবে।
skia.heliou

finalক্ষেত্রগুলি বোধগম্য হয় কেবল যদি ক্ষেত্রের সর্বদা প্রাথমিককরণের সময় প্রয়োজন হয়। যদি না হয়, তবে ক্ষেত্রগুলি হওয়া উচিত নয় final
পিয়োট্রেইক হিরিয়ুক

12

আপনি একটি স্থিতিশীল উপায়ে একটি অ স্থিত শ্রেণীর অ্যাক্সেস চেষ্টা করছেন। পরিবর্তন Builderকরুন static class Builderএবং এটি কাজ করা উচিত।

আপনার দেওয়া উদাহরণের ব্যবহার ব্যর্থ হয়েছে কারণ উপস্থিতের কোনও উদাহরণ নেই Builder। সমস্ত ব্যবহারিক উদ্দেশ্যে একটি স্ট্যাটিক বর্গ সর্বদা তাত্ক্ষণিক হয়। আপনি যদি এটি স্থির না করেন তবে আপনার এই কথাটি বলা দরকার:

Widget = new Widget.Builder(10).setparm1(1).setparm2(3).build();

কারণ আপনার Builderপ্রত্যেকবার একটি নতুন নির্মাণ করা প্রয়োজন ।


12

ইন্টেলিজ আইডিইএতে একটি অভ্যন্তরীণ বিল্ডার তৈরি করতে, এই প্লাগইনটি দেখুন: https://github.com/analytically/innerbuilder


2
জিজ্ঞাসা করা প্রশ্নটির সাথে এর কোনও সম্পর্ক নেই তবে খুব সহায়ক! ভাল লাগছে!
হাংরি অ্যান্ড্রয়েডার

8

আপনাকে Builderঅভ্যন্তরীণ শ্রেণিকে যেমন ঘোষণা করতে হবে static

অ স্থিতিশীল অভ্যন্তর শ্রেণি এবং স্থির অভ্যন্তর শ্রেণীর উভয়ের জন্য কিছু ডকুমেন্টেশনের পরামর্শ নিন ।

মূলত অ স্থিতিশীল অভ্যন্তর শ্রেণীর উদাহরণগুলি সংযুক্ত বাইরের শ্রেণীর উদাহরণ ব্যতীত উপস্থিত থাকতে পারে না।


5

একবার আপনি ধারণা পেয়ে গেলে, বাস্তবে, আপনি লম্বোকের @Builderআরও অনেক সুবিধাজনক দেখতে পাবেন ।

@Builder আপনার ক্লাসটি কোডের সাথে তাত্ক্ষণিক হওয়ার জন্য প্রয়োজনীয় কোডটি স্বয়ংক্রিয়ভাবে আপনাকে উত্পাদন করতে দেয়:

Person.builder()
  .name("Adam Savage")
  .city("San Francisco")
  .job("Mythbusters")
  .job("Unchained Reaction")
 .build(); 

অফিসিয়াল ডকুমেন্টেশন: https://www.projectlombok.org/features/ বিল্ডার


4

এর অর্থ হ'ল আপনি ঘেরের ধরণ তৈরি করতে পারবেন না। এর অর্থ হ'ল প্রথমে আপনাকে "প্যারেন্ট" শ্রেণীর একটি উদাহরণ সরিয়ে ফেলতে হবে এবং তারপরে এই উদাহরণটি থেকে আপনি নেস্টেড বর্গের উদাহরণ তৈরি করতে পারেন।

NutritionalFacts n = new NutritionalFacts()

Builder b = new n.Builder(10).carbo(23).fat(1).build();

নেস্টেড ক্লাস


3
এটি খুব একটা বোঝায় না, কারণ তার অন্যদিকে নয়, "ফ্যাক্টস" তৈরির জন্য বিল্ডারের প্রয়োজন।
বোজহো

5
সত্য যদি আমরা বিল্ডার প্যাটার্নটিতে মনোনিবেশ করি তবে আমি কেবল "বার্তাটির অর্থ বুঝতে পারি না" তে মনোনিবেশ করেছি এবং দুটি সমাধানের মধ্যে একটি উপস্থাপন করেছি।
দামিয়ান লেজস্কিওস্কি - ভ্যাশ

3

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


1

আমি ব্যক্তিগতভাবে অন্যান্য পদ্ধতির ব্যবহার করতে পছন্দ করি, যখন আপনার 2 টি আলাদা ক্লাস থাকে। সুতরাং আপনার কোনও স্ট্যাটিক ক্লাসের দরকার নেই। এটি Class.Builderযখন আপনাকে একটি নতুন উদাহরণ তৈরি করতে হয় তখন এড়ানো মূলত to

public class Person {
    private String attr1;
    private String attr2;
    private String attr3;

    // package access
    Person(PersonBuilder builder) {
        this.attr1 = builder.getAttr1();
        // ...
    }

    // ...
    // getters and setters 
}

public class PersonBuilder (
    private String attr1;
    private String attr2;
    private String attr3;

    // constructor with required attribute
    public PersonBuilder(String attr1) {
        this.attr1 = attr1;
    }

    public PersonBuilder setAttr2(String attr2) {
        this.attr2 = attr2;
        return this;
    }

    public PersonBuilder setAttr3(String attr3) {
        this.attr3 = attr3;
        return this;
    }

    public Person build() {
        return new Person(this);
    }
    // ....
}

সুতরাং, আপনি আপনার বিল্ডারটিকে এভাবে ব্যবহার করতে পারেন:

Person person = new PersonBuilder("attr1")
                            .setAttr2("attr2")
                            .build();

0

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

এই বিবেচনা. withProperty(value)শ্রেণীর অভ্যন্তরে টাইপ সেটারগুলির মতো কিছু ঘোষণা করে কোনও বিল্ডারকে বাস্তবায়ন করা এবং তাদের নিজের কাছে একটি রেফারেন্স ফিরিয়ে দেওয়া। এই পদ্ধতির ক্ষেত্রে আপনার একটি একক এবং মার্জিত ক্লাস রয়েছে যা একটি থ্রেড নিরাপদ এবং সংক্ষিপ্ত।

এই বিবেচনা:

public class DataObject {

    private String first;
    private String second;
    private String third;

    public String getFirst(){
       return first; 
    }

    public void setFirst(String first){
       this.first = first; 
    }

    ... 

    public DataObject withFirst(String first){
       this.first = first;
       return this; 
    }

    public DataObject withSecond(String second){
       this.second = second;
       return this; 
    }

    public DataObject withThird(String third){
       this.third = third;
       return this; 
    }
}


DataObject dataObject = new DataObject()
     .withFirst("first data")
     .withSecond("second data")
     .withThird("third data");

আরও জাভা নির্মাতার উদাহরণের জন্য এটি পরীক্ষা করে দেখুন ।


0

আপনার বিল্ডার শ্রেণিটি স্থিতিশীল শ্রেণীর বিল্ডারে পরিবর্তন করা দরকার । তাহলে এটি ঠিকঠাক কাজ করবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.