2013-03-14 12 views
13

पर बिल्डर पैटर्न का उपयोग कर सकता हूं, मैं कुछ कोड दोबारा लिख ​​रहा हूं, और मैंने कक्षा को फिर से बनाने का तरीका तय किया है, क्योंकि निश्चित संख्या में चादरें हैं, मैं उन्हें enums के रूप में बना रहा हूं । यह एक टेलीस्कोपिंग कन्स्ट्रक्टर बनाम बिल्डर पटर की पठनीयता के आधार पर एक निर्णय है।क्या मैं जावा एनम

कोड मैं कुछ .xls फ़ाइलों को पकड़ता हूं, हेडर जोड़ता है (और अन्य .xls फ़ाइलों से कुछ पढ़ता है) और शायद कुछ सब-शीट्स। इसके बाद यह मुख्य एक्सेल कार्यपुस्तिका पर टैब बनाने के लिए एक विशिष्ट तरीके से इन चादरों में से एक को विलय करता है। मेरी समस्या यह है कि कुछ कार्यपुस्तिका टैब विभिन्न चादरें लेते हैं तर्क हैं। मैं बिल्डर पैटर्न को लागू करने की कोशिश कर रहा हूं।

public enum workBookSheet { 
    mySheet1("Name1","mainSheet1.xls",true,1).addSubSheet("pathToSubSheet1.xls"), 
    mySheet2("Name2","mainSheet2.xls",true,2).addHeaderSheet("pathToHeaders.xls").addSubsheet("pathtoSubSheet2.xls"); 

    private String tabName; 
    private String mainSheetName; 
    private Boolean available; 
    private Integer order; 
    private String subSheetName; 
    private String headerSheetName; 

    private workBookSheet(String tabName, String mainSheetName, Boolean available, Integer order){ 
     this.tabName = tabName; 
     this.mainSheetName = mainSheetName; 
     this.available = available; 
     this.order = order; 
    } 
    public workBookSheet addSubSheet(String subSheetName){ 
     this.subSheetName = subSheetName; 
     return this; 
    } 
    public workBookSheet addHeaderSheet(String headerSheetName){ 
     this.headerSheetName = headerSheetName; 
     return this; 
    } 

} 

त्रुटि है कि जावा दे रहा है (अल्पविराम शीर्ष पर सीमांकित 'enum कंस्ट्रक्टर्स की सूची) ने मुझे बताया है कि जावा मेरी enum घोषणा की उम्मीद लगती है: इस कोड की तरह मैं लिखने के लिए कोशिश कर रहा हूँ है इसमें केवल निर्माता ही है, और अतिरिक्त तरीकों से नहीं। मैं शिकायत के बिना उन तरीकों को नीचे 'बिल्डर' विधि में स्थानांतरित कर सकता हूं।

public void buildSheets(){ 
    mySheet1.addSubSheet("pathToSubSheet1.xls"); 
    mySheet2.addHeaderSheet("pathToHeaders.xls").addSubSheet("pathtoSubSheet2.xls"); 
} 

यह एक enum पर एक बिल्डर पैटर्न लागू करने के लिए एक ही रास्ता है? मुझे एक अलग विधि चलाने की आवश्यकता है, जो बहुत अधिक परेशानी नहीं है। आईटी कैसा लगता है जैसे मैं पैटर्न को तोड़ने के कर रहा हूँ, हालांकि (मैं इस तरह के एक बुरी बात लगता है, नहीं है कि अगर यह काम करता है।)

नायब मैं इतने पर चारों ओर देखने के लिए अगर किसी और को इस सवाल से कहा है कि अच्छी तरह से देखने मिला है, या वेब पर कहीं और। मैंने पाया सबसे नज़दीकी Enums और कारखानों पर एक सवाल था, लेकिन यह मेरे सवाल का काफी जवाब नहीं है। इसके अलावा मुझे पता है कि यह काफी बिल्डर पैटर्न नहीं है, क्योंकि मेरे पास एक अलग वर्ग नहीं है जो तब एक बिल्ड() विधि स्वीकार करता है जो एक नया enum बनाता है। मुझे लगता है कि यह मेरे प्रारंभिक डिजाइन में समस्या की जड़ है, लेकिन मैं जावा के लिए अपेक्षाकृत नया हूं।

तो क्या जावा एनम पर बिल्डर पैटर्न का उपयोग करने का कोई बेहतर तरीका है? या मेरे पास 'पर्याप्त करीब' है? (पैरामीटर निर्माता को पारित करने के लिए)

उत्तर

14

हालांकि यह निर्माता के पैटर्न के अनुरूप सख्ती से पालन नहीं करता है, तो संक्षिप्त उत्तर हाँ है। की तरह।

गायब टुकड़ा, enum निरंतर का दृष्टांत को .build() कॉल करने के लिए सक्षम नहीं किया जा रहा है क्योंकि निर्माण() new उपयोग नहीं कर सकते। लेकिन आप बिल्डर पैटर्न के कुछ फायदे प्राप्त कर सकते हैं।और चलो इसका सामना करते हैं, आप स्थैतिक फैक्ट्री विधियों का उपयोग नहीं कर सकते हैं, और enum स्थिरांक की इनलाइन उपclassing अजीब है।

यहां देश गणना का उपयोग करके एक उदाहरण दिया गया है।

package app; 

import org.apache.commons.lang.StringUtils; 
import javax.annotation.Nullable; 
import java.util.EnumSet; 
import java.util.Set; 
import static app.Language.*; 
import static com.google.common.base.Preconditions.*; 

enum Language { 
    ITALIAN, 
    ENGLISH, 
    MALTESE 
} 

public enum Country { 

    ITALY(new Builder(1, "Italy").addLanguage(ITALIAN)), 
    MALTA(new Builder(2, "Malta").addLanguages(MALTESE, ENGLISH, ITALIAN).setPopulation(450_000)); 

    final private int id; 
    final private String name; 
    final private Integer population; 
    final private Set<Language> languages; 

    private static class Builder { 

     private int id; 
     private String name; 
     private Integer population; 
     private Set<Language> languages = EnumSet.noneOf(Language.class); 

     public Builder(int id, String name) { 
      checkArgument(!StringUtils.isBlank(name)); 

      this.id = id; 
      this.name = name; 
     } 

     public Builder setPopulation(int population) { 
      checkArgument(population > 0); 

      this.population = population; 
      return this; 
     } 

     public Builder addLanguage(Language language) { 
      checkNotNull(language); 

      this.languages.add(language); 
      return this; 
     } 

     public Builder addLanguages(Language... language) { 
      checkNotNull(language); 

      this.languages.addAll(languages); 
      return this; 
     } 
    } 

    private Country(Builder builder) { 

     this.id = builder.id; 
     this.name = builder.name; 
     this.population = builder.population; 
     this.languages = builder.languages; 

     checkState(!this.languages.isEmpty()); 
    } 

    public int getId() { 
     return id; 
    } 

    public String getName() { 
     return name; 
    } 

    @Nullable 
    public Integer getPopulation() { 
     return population; 
    } 

    public Set<Language> getLanguages() { 
     return languages; 
    } 
} 

यदि आप स्थिर बनाने के सामान्य तरीके हैं तो आप बिल्डर में स्थैतिक फैक्ट्री विधियां भी डाल सकते हैं।

तो यह काफी ब्लोच का निर्माता नहीं है, लेकिन यह बहुत करीब है।

+0

क्या यह ऐसा कुछ है जिसे आपने पहले उपयोग किया है, या यह नया कोड है जिसे आपने एक उदाहरण के रूप में लिखा है? – Pureferret

+3

दोनों का थोड़ा सा। मैं एक निर्माता का उपयोग करना चाहता था, कुछ जवाब मिला लेकिन उन्हें पसंद नहीं आया, और इस तरह से ऐसा करने के साथ आया। तब मैंने सोचा कि अगर मैं किसी की मदद करता हूं तो मैं इस समाधान में अपना समाधान साझा करूंगा। –

+1

आपको बहुत बहुत धन्यवाद! इसने मेरी enum कक्षा को और अधिक पठनीय बना दिया। –

1

mySheet1, mySheet2, आदि enum स्थिरांक जो JLS वाक्य रचना अनुभाग में परिभाषित 8.9.1

EnumConstant: Annotationsopt Identifier Argumentsopt ClassBodyopt

तो इस प्रकार हैं, तो आप enum एक तर्क सूची से निरंतर पालन कर सकते हैं लेकिन आप इसे घोषित करते समय enum निरंतर पर एक विधि कॉल नहीं कर सकते हैं। अधिकतर आप इसके लिए एक क्लास बॉडी जोड़ सकते हैं।

इस के अलावा, बिल्डर पैटर्न के आपके उपयोग enum उदाहरणों के निर्माण के लिए संदिग्ध है आप एक के लिए इस्तेमाल किया enums की अवधारणा के साथ इसके विपरीत में उदाहरणों की एक बड़ी संख्या (फ़ील्ड मानों का संयोजन) हैं तो सामान्य रूप में के रूप में बिल्डर पैटर्न प्रयोग किया जाता है कुछ उदाहरण

+0

विशेष रूप से परिभाषाओं को इंगित करने के लिए, आपके उत्तर dcernahoschi के लिए धन्यवाद। हकीकत में, मेरे पास वास्तव में खेल में 20-25 एनम उदाहरण होते हैं, प्रत्येक में हेडर, सब-चादर आदि का एक अलग संयोजन होता है। एक निर्माता को उचित ठहराने के लिए कितने 'बड़े' होते हैं, कितने 'कम' के लिए पर्याप्त कुछ है enum? अधिक विकास के साथ, यह बदल सकता है (कक्षा में बाद में हार्ड कोड किए गए हेडर को हेडर.एक्सएल शीट आदि में परिवर्तित किया जा सकता है) इसलिए यह पैटर्न मेरे लिए उपयुक्त महसूस करता है। – Pureferret

4

आप मनमाने ढंग से कोड के साथ निर्माण अनुकूलित करने के लिए उदाहरण के ब्लॉक (अक्सर गलत तरीके से कहा जाता है "डबल ब्रेस initializers") का उपयोग कर सकते हैं:

public enum workBookSheet { 

    mySheet1("Name1", "mainSheet1.xls", true, 1) {{ 
     addSubSheet("pathToSubSheet1.xls"); 
    }}, 
    mySheet2("Name2", "mainSheet2.xls", true, 2) {{ 
     // you can use the fluent interface: 
     addHeaderSheet("pathToHeaders.xls").addSubSheet("pathtoSubSheet2.xls"); 
     // but I would prefer coding separate statements: 
     addHeaderSheet("pathToHeaders.xls"); 
     addSubSheet("pathtoSubSheet2.xls"); 
    }}; 

    // rest of your class the same... 
} 

आप सीमाओं एक enum द्वारा लगाए गए आस-पास काम करने के लिए अनुमति देता है इस वाक्य को रोजगार लेकिन अभी भी एक निर्माता/धाराप्रवाह पैटर्न की संक्षिप्तता, सुविधा और लचीलापन है।

+0

यह एक बहुत चालाक है! मेरे एकमात्र प्रश्न हैं: क्या मुझे विधियों को संशोधित करना है, और क्या मैं उदाहरण ब्लॉक सामग्री को 'this.methodName (...); 'के रूप में लिख सकता हूं, क्योंकि मैं विधियों को लिखते समय स्पष्ट होना पसंद करता हूं। – Pureferret

+1

आपको विधियों को संशोधित करने के लिए * की आवश्यकता नहीं है, हालांकि मैं धाराप्रवाह शैली से परेशान नहीं होगा ('यह' लौट रहा हूं) और मैं तब तक' निजी 'बनाउंगा, जब तक कि आपको * अपनी कक्षा के बाहर दिखाई देने की आवश्यकता न हो। आप 'यह' लिख सकते हैं, लेकिन यह अनावश्यक है और शैली के दृष्टिकोण से अनुशंसित नहीं है, विशेष रूप से क्योंकि 'इस' * के तरीकों को योग्यता की आवश्यकता नहीं है; केवल फ़ील्ड को क्वालीफाइंग की आवश्यकता होती है और केवल तभी जब वे पैरामीटर नामों के साथ संघर्ष करते हैं, और उदाहरण ब्लॉक के लिए कोई पैरामीटर नहीं हैं। – Bohemian

+0

बोहेमियन, मैंने इंस्टेंस ब्लॉक का उपयोग करने की कोशिश की है, लेकिन कक्षाओं के अंदर की कक्षा स्थिर है, और उन्हें जगह में डालने का मतलब है कि वे त्रुटि करते हैं। मैं उन्हें छोड़ रहा हूं क्योंकि वे अभी के लिए हैं, लेकिन अगर मुझे समय लगता है तो मैं इसके आसपास काम करने की कोशिश करूंगा। अभी के लिए, यदि आप जानते हैं कि विधियों की तरह क्या दिखना चाहिए, तो क्या आप उन्हें जवाब में पॉप कर सकते हैं? – Pureferret

संबंधित मुद्दे