IntelliJ में बिल्डर पैटर्न कोड जनरेशन


83

IntelliJ में बिल्डर पैटर्न लिखने को स्वचालित करने का कोई तरीका है?

उदाहरण के लिए, यह सरल वर्ग दिया गया है:

class Film {
   private String title;
   private int length;

   public void setTitle(String title) {
       this.title = title;
   }

   public String getTitle() {
       return this.title;
   }

   public void setLength(int length) {
       this.length = length;
   }

   public int getLength() {
       return this.length;
   }
}

क्या कोई ऐसा तरीका है जिससे मैं इसे उत्पन्न करने के लिए IDE प्राप्त कर सकता हूं, या इसी तरह:

public class FilmBuilder {

    Film film;

    public FilmBuilder() {
        film = new Film();
    }

    public FilmBuilder withTitle(String title) {
        film.setTitle(title);
        return this;
    }

    public FilmBuilder withLength(int length) {
        film.setLength(length);
        return this;
    }

    public Film build() {
        return film;
    }
}

जवाबों:


108

बिल्डर रिऐक्टरिंग के साथ रिप्लेसमेंट कंस्ट्रक्टर का उपयोग करें ।

इस फ़ंक्शन का उपयोग करने के लिए, अपने कोड में निर्माणकर्ता के हस्ताक्षर पर क्लिक करें, फिर राइट क्लिक करें और "Refactor" मेनू का चयन करें, फिर कोड बनाने के लिए डायलॉग बॉक्स लाने के लिए "बिल्डर के साथ कंस्ट्रक्टर बदलें ..." पर क्लिक करें।


12
क्या "setX ()" को "withX ()", सर्ज में बदलने का कोई तरीका है?
ae6rt 19

5
या आप सेट x () को सिर्फ x () में बदल सकते हैं?
कुरु

अच्छा! कभी नया जो अस्तित्व में नहीं था। धन्यवाद
vikingsteve

16
आप बिल्डर विंडो के ऊपरी दाएँ हाथ के कोने में गियर पर क्लिक करके और "सेटर्स प्रीफ़िक्स उपसर्ग" का चयन करके सेटर के तरीकों का नाम बदल सकते हैं। फिर आप इसे "के साथ" बदल सकते हैं या बस उपसर्ग को पूरी तरह से हटा सकते हैं।
क्रिस बी

3
क्या इंटेलीजे को बिल्डर वर्ग बनाना एक आंतरिक वर्ग के रूप में स्वचालित रूप से संभव है?
किट

23

मैंने पाया कि इन्टेलिज में बिल्ट-इन बिल्डर पैटर्न जेनरेशन कुछ कारणों से थोड़ा क्लंकी है:

  1. इसे संदर्भ के रूप में मौजूदा निर्माता का उपयोग करने की आवश्यकता है।
  2. यह "जेनरेट" मेनू ( command+Nओएस एक्स पर) के माध्यम से जल्दी से सुलभ नहीं है ।
  3. यह केवल बाहरी बिल्डर कक्षाएं उत्पन्न करता है। जैसा कि दूसरों ने उल्लेख किया है, बिल्डर पैटर्न को लागू करते समय स्थिर आंतरिक वर्गों का उपयोग करना बहुत आम है।

InnerBuilder प्लगइन इन सभी कमियों के पते, और कोई सेटअप या विन्यास की आवश्यकता है। यहाँ प्लगइन द्वारा उत्पन्न एक नमूना बिल्डर है:

public class Person {
    private String firstName;
    private String lastName;
    private int age;

    private Person(Builder builder) {
        firstName = builder.firstName;
        lastName = builder.lastName;
        age = builder.age;
    }

    public static final class Builder {
        private String firstName;
        private String lastName;
        private int age;

        public Builder() {
        }

        public Builder firstName(String firstName) {
            this.firstName = firstName;
            return this;
        }

        public Builder lastName(String lastName) {
            this.lastName = lastName;
            return this;
        }

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

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

3
कृपया, अपनी सभी वर्णित समस्याओं के अंतर्निहित समाधान के लिए मेरा उत्तर देखें ।
jFrenetic

1
आप कुछ अच्छे अंक बनाते हैं @jFrenetic, लेकिन मैं अभी भी अन्तर्निहित दृष्टिकोण को बहुत बोझिल होने के लिए खोजता हूं, यहां तक ​​कि उन वर्कअराउंड के साथ भी। प्लगइन के साथ, यह सचमुच है alt+shift+B, enterऔर BAM, आप अपने बिल्डर की है। : डी
मंसूर सिद्दीकी

1
OMG यह एक सपना सच होने जैसा है। बिल्डर में बनाया यह मेरे लिए नहीं किया - मैं PoJo के एक आंतरिक वर्ग के रूप में बिल्डर है पसंद करते हैं। एक सुंदर टिप धन्यवाद!
सोमाया कुम्बरा

16

यहां देखें मंसूर सिद्दीकी द्वारा बताई गई कमियों को दूर करने का तरीका :

1) इसे संदर्भ के रूप में मौजूदा निर्माता का उपयोग करने की आवश्यकता है।

जिसे जनरेट करना बहुत ही आसान है। बस मारा Alt+ InsWindows पर मेनू उत्पन्न और चुनें आह्वान करने के लिए Constructor

2) यह "जेनरेट" मेनू (ओएस एक्स पर कमांड + एन) के माध्यम से जल्दी से सुलभ नहीं है

बस में जाएं Settings -> Keymap, Builderइसे खोजें और इसे अपनी पसंद का शॉर्टकट असाइन करें (यदि आप इस कार्यक्षमता का उपयोग अक्सर करते हैं, जो शायद ही कभी होता है)। आप उदाहरण के लिए Alt+ असाइन कर सकते हैं B

एक अन्य विकल्प Ctrl+ Shift+ A(एक्शन ढूंढें) है। टाइप करना शुरू करें Builderऔर आपको तुरंत कमांड की सुविधा मिलेगी:

एक्शन संवाद खोजें

आप इस शॉर्टकट का उपयोग किसी भी IntelliJ IDEA सुविधा के लिए जल्दी से कर सकते हैं (यह बहुत मदद करता है जब आपको याद नहीं होता है कि वास्तव में कमांड क्या कहा जाता है और इसे कहां खोजना है)।

3) यह केवल बाहरी बिल्डर कक्षाएं उत्पन्न करता है। जैसा कि दूसरों ने उल्लेख किया है, बिल्डर पैटर्न को लागू करते समय स्थिर आंतरिक वर्गों का उपयोग करना बहुत आम है ।

मैं अपने बिल्डरों को स्थिर आंतरिक वर्गों के रूप में पसंद करता हूं। दुर्भाग्य से, ऐसा करने का कोई सीधा तरीका नहीं है, लेकिन यह अभी भी संभव है। आपको बस खुद को नेस्टेड इनर क्लास को परिभाषित करना है (इसे खाली छोड़ दें), और जब आप Replace Constructor with Builderडायलॉग को इनवॉइस करते हैं , तो Use existingविकल्प चुनें और अपने आंतरिक वर्ग का चयन करें। एक जादू की तरह काम करता है! हालाँकि, इस विकल्प को विन्यास योग्य बनाना आसान था।


12

यदि आप सोच रहे हैं कि क्या इसका उपयोग जोशुआ ब्लॉक द्वारा वर्णित आंतरिक बिल्डर वर्ग के साथ एक वर्ग बनाने के लिए किया जा सकता है - आपको बस एक खाली आंतरिक वर्ग को परिभाषित करना है, तो "मौजूदा का उपयोग करें" जांचें और अपने नए बनाए गए (आंतरिक वर्ग) को खोजें ) और हिट "रिफ्लेक्टर"।

पुनश्च! "रिप्लेसमेंट कंस्ट्रक्टर विद बिल्डर" रिफैक्टरिंग फ़ंक्शन का उपयोग करने के लिए कर्सर को कंस्ट्रक्टर (पूर्व लिखित) के अंदर रहना चाहिए।


यह दिलचस्प है कि ये प्लगइन्स बिल्डर पैटर्न का एक महत्वपूर्ण हिस्सा भूल जाते हैं: आपको अभी भी कंस्ट्रक्टर में आवश्यक पार्म्स को परिभाषित करना चाहिए। अन्यथा, आप केवल समय पर रनिंग को पकड़ने के लिए स्टैटिक रूप से लापता परम त्रुटियों को पकड़ रहे हैं।
ईजे कैंपबेल

@EJCampbell एक बिल्डर का उपयोग करने के उद्देश्यों में से एक को हरा देगा , जो कि मापदंडों को नाम संलग्न करने का एक तरीका प्रदान करके कोड को अधिक पठनीय बनाना है, भले ही वे आवश्यक हों। यह तब मदद करता है जब एक निर्माता काफी बड़ी संख्या में पैरामीटर लेता है। यह आवश्यक नहीं होगा यदि जावा हमें कॉल में वास्तविक मापदंडों का नाम देने की अनुमति देता है, जैसे सी # और स्विफ्ट करते हैं।
अंजब a

5

यह करने के लिए IntelliJ रास्ता है, IMHO, दृढ़ है। वहाँ दो प्लगइन्स हैं (मुझे यह पसंद है: https://plugins.jetbrains.com/plugin/7354 ) जो उद्देश्य को बहुत बेहतर तरीके से पूरा करते हैं।

उदाहरण के लिए, मैं बिल्डर क्लास को PoJo के आंतरिक वर्ग के रूप में पसंद करता हूं। IntelliJ के साथ इसे प्राप्त करने के लिए आपको कुछ अतिरिक्त स्ट्रोक की आवश्यकता है।

प्लगइन के लिए एक और प्लस कार्यक्षमता का स्थान है ( Generate...संदर्भ मेनू में)।


4

लोम्बोक इसे करने का सबसे आसान तरीका है! (इसमें सिंटैक्स सपोर्ट https://plugins.jetbrains.com/plugin/6317-lombok-plugin के लिए एक Intellij प्लगइन है )

बस एक @Builderएनोटेशन जोड़ें , और दीवारों के पीछे यह ऑब्जेक्ट के अंदर एक बिल्डर कार्यान्वयन जोड़ देगा।

लोम्बोक के साथ:

import lombok.Builder;
import lombok.Singular;
import java.util.Set;

@Builder
public class BuilderExample {
  @Builder.Default private long created = System.currentTimeMillis();
  private String name;
  private int age;
  @Singular private Set<String> occupations;
}

लोम्बोक के बिना:

import java.util.Set;

public class BuilderExample {
  private long created;
  private String name;
  private int age;
  private Set<String> occupations;
  
  BuilderExample(String name, int age, Set<String> occupations) {
    this.name = name;
    this.age = age;
    this.occupations = occupations;
  }
  
  private static long $default$created() {
    return System.currentTimeMillis();
  }
  
  public static BuilderExampleBuilder builder() {
    return new BuilderExampleBuilder();
  }
  
  public static class BuilderExampleBuilder {
    private long created;
    private boolean created$set;
    private String name;
    private int age;
    private java.util.ArrayList<String> occupations;
    
    BuilderExampleBuilder() {
    }
    
    public BuilderExampleBuilder created(long created) {
      this.created = created;
      this.created$set = true;
      return this;
    }
    
    public BuilderExampleBuilder name(String name) {
      this.name = name;
      return this;
    }
    
    public BuilderExampleBuilder age(int age) {
      this.age = age;
      return this;
    }
    
    public BuilderExampleBuilder occupation(String occupation) {
      if (this.occupations == null) {
        this.occupations = new java.util.ArrayList<String>();
      }
      
      this.occupations.add(occupation);
      return this;
    }
    
    public BuilderExampleBuilder occupations(Collection<? extends String> occupations) {
      if (this.occupations == null) {
        this.occupations = new java.util.ArrayList<String>();
      }

      this.occupations.addAll(occupations);
      return this;
    }
    
    public BuilderExampleBuilder clearOccupations() {
      if (this.occupations != null) {
        this.occupations.clear();
      }
      
      return this;
    }

    public BuilderExample build() {
      // complicated switch statement to produce a compact properly sized immutable set omitted.
      Set<String> occupations = ...;
      return new BuilderExample(created$set ? created : BuilderExample.$default$created(), name, age, occupations);
    }
    
    @java.lang.Override
    public String toString() {
      return "BuilderExample.BuilderExampleBuilder(created = " + this.created + ", name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";
    }
  }
}

स्रोत: https://projectlombok.org/features/Builder


lombok अतिरिक्त चरणों के साथ कोड पीढ़ी है। इसकी वजह से कई स्थिर विश्लेषण उपकरण भ्रमित होते हैं क्योंकि अंतिम कोड जो वे पढ़ते हैं वह जावा की तरह नहीं दिखता है।
ThisCompSciGuy

2

मेरी राय में, एक अलग के बजाय आंतरिक स्थिर वर्ग प्राप्त करने का सबसे सरल तरीका है:

  1. यदि आपके पास अभी तक एक निर्माता नहीं है, तो एक निर्माता संवाद का उपयोग करके उत्पन्न करें
  2. फिर, बिल्डर के साथ बदलें कंस्ट्रक्टर का उपयोग करें
  3. मूव रिफ्लेक्टिंग (हॉटकी: F6) का उपयोग करके नए बनाए गए वर्ग को प्रारंभिक पर वापस ले जाएं

1
यह प्लगइन केवल एक चरण में वास्तव में इसे प्राप्त करता है: plugins.jetbrains.com/plugin/7354-innerbuilder
jivimberg

0

@ CrazyCoder के उत्तर के पूरक के रूप में, मुझे लगता है कि यह जानना बहुत उपयोगी है कि बिल्डर संवाद के साथ रिप्लेसमेंट कंस्ट्रक्टर के ऊपरी-दाहिने हिस्से में एक कॉन्फ़िगरेशन बटन है जिसका उपयोग आप उपनिवेश के उपसर्ग का नाम बदलने के लिए कर सकते हैं।


0

एक बिल्डर पैटर्न के साथ "बहुत सारे मापदंडों" को बदलने के इच्छुक लोगों के लिए, "अर्क पैरामीटर ऑब्जेक्ट" करें और फिर अन्य उत्तर में उल्लिखित बिल्डर को बिल्डर में कनवर्ट करें।


0

क्लास जनरेट> कंस्ट्रक्टर पर राइट क्लिक करके क्लास के कंस्ट्रक्टर को जेनरेट करें। फिर, विंडोज पर, एक्शन खोजने के लिए Ctrl + Shift + A दबाएं और "बिल्डर" टाइप करें, "रिप्लेस कंस्ट्रक्टर विथ बिल्डर" चुनें।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.