2012-06-29 7 views
8

www.dofactory.com पर मुझे फैक्टरी पैटर्न का असली दुनिया उदाहरण मिला। लेकिन कोड पुनर्विक्रेता में वर्चुअल सदस्य कॉल के बारे में ReSharper में एक चेतावनी उत्पन्न करता है।फैक्टरी विधि पैटर्न को कैसे रोकें कन्स्ट्रक्टर में वर्चुअल सदस्य कॉल के बारे में चेतावनी उत्पन्न करना?

कोड चेतावनी के कारण निम्नलिखित है:

abstract class Document 
{ 
    private List<Page> _pages = new List<Page>(); 

    // Constructor calls abstract Factory method 
    public Document() 
    { 
     this.CreatePages(); // <= this line is causing the warning 
    } 

    public List<Page> Pages 
    { 
     get { return _pages; } 
    } 

    // Factory Method 
    public abstract void CreatePages(); 
} 

class Resume : Document 
{ 
    // Factory Method implementation 
    public override void CreatePages() 
    { 
     Pages.Add(new SkillsPage()); 
     Pages.Add(new EducationPage()); 
     Pages.Add(new ExperiencePage()); 
    } 
} 

लेने वाली कोड में, आप कर सकते हैं तो बस का उपयोग करें:

Document document = new Resume(); 

मुझे समझ नहीं क्यों यह एक बुरा विचार एक आभासी कॉल करने के लिए है निर्माता में सदस्य (जैसा कि here समझाया गया है)।

मेरा सवाल यह है कि आप अभी भी फैक्ट्री पैटर्न का उपयोग करने के लिए इसे पुन: सक्रिय कर सकते हैं, लेकिन कन्स्ट्रक्टर में वर्चुअल सदस्य कॉल के बिना।

मैं सिर्फ निर्माता से CreatePages का कॉल निकालना चाहते हैं, तो उपभोक्ता को स्पष्ट रूप से कॉल करने के लिए होता है CreatePages विधि:

Document document = new Resume(); 
document.CreatePages(); 

मैं भी बहुत कुछ स्थिति है जहाँ एक नया Resume बनाने पसंद करते हैं कि सभी है वास्तव में पृष्ठों को फिर से शुरू करने के लिए आवश्यक है।

+0

बस 'फिर से शुरू करें' को 'मुहरबंद' के रूप में चिह्नित करें? – EkoostikMartin

+1

@EkoostikMartin क्या होगा यदि ओपी कल उठ जाएगा 'स्टाइलिश रेज़्यूम: फिर से शुरू करें' घोषित करना चाहते हैं? –

+0

@EkoostikMartin: मैं सिर्फ चेतावनी को दूर नहीं जाना चाहता, मैं जानना चाहता हूं कि यह और कैसे लागू किया जा सकता है। फिर भी 'रेज़्यूमे' को उपclass करना संभव बनाता है। – comecme

उत्तर

2

एक तरह से पृष्ठों अग्रिम गुजर जाएगा, और उन्हें एक संरक्षित निर्माता को गुजर:

public abstract class Document { 
    protected Document(IEnumerable<Page> pages) { 
     // If it's OK to add to _pages, do not use AsReadOnly 
     _pages = pages.ToList().AsReadOnly(); 
    } 
    // ... 
} 

public class Resume : Document { 
    public Resume() : base(CreatePages()) { 
    } 
    private static IEnumerable<Page> CreatePages() { 
     return new Page[] { 
      new SkillsPage(), 
      new EducationPage(), 
      new ExperiencePage() 
     }; 
    } 
} 

पी.एस. मुझे यकीन नहीं है कि फैक्ट्री विधि के साथ इसका क्या संबंध है। आपकी पोस्ट Template Method Pattern दिखाती है।

+0

[dofactory.com] के अनुसार (http://www.dofactory.com/Patterns/PatternFactory.aspx) यह एक कारखाने विधि का एक उदाहरण है। क्या वे गलत हैं? – comecme

+2

@comecme हां, मैं निश्चित रूप से निश्चित हूं कि वे गलत हैं: एक बात के लिए, फैक्ट्री विधि 'शून्य' नहीं हो सकती है, इसे कुछ वापस करना होगा। – dasblinkenlight

0

आप संपत्ति में ही कर सकते हैं।

उस स्थिति में Pages संपत्ति को बेस क्लास में virtual के रूप में चिह्नित किया जा सकता है।

Resume के लिए कल्पना का कोड ऐसा दिखाई दे सकता:

private List<Page> _pages = null; 
    public override List<Page> Pages 
    { 
      get 
      { 
       if(pages == null) 
       { 
        _pages = new List<Page>(); 
        _pages .Add(new SkillsPage()); 
        _pages .Add(new EducationPage()); 
        _pages .Add(new ExperiencePage()); 
       } 

       return _pages; 
      } 

     } 
    } 

इस मामले में, पृष्ठों पहले उपयोग पर Pages संपत्ति, और नहींctor निष्पादन पर करने के लिए बनाया जाएगा। इस refactor करने के लिए

+0

मुझे नहीं लगता कि यह फैक्ट्री विधि के रूप में योग्य होगा, क्योंकि अब कोई विधि नहीं है। – comecme

+0

ठीक है, आप 'विधि' जैसे 'प्रॉपर्टी' का उपयोग करते हैं। आप विधि सदस्यों के साथ मुश्किल से जोड़े क्यों चाहते हैं ... – Tigran

1

इसके बारे में क्या? यह आलसी प्रारंभिकता का उपयोग करता है जहां पेज केवल तभी बनाए जाते हैं जब उन्हें आवश्यक होता है (उन्हें कन्स्ट्रक्टर में बनाने के बजाए)

साथ ही, ध्यान दें कि फैक्टरी विधि दृश्यता protected पर सार्वजनिक उपयोग से छिपाने के लिए बदल दी गई है।

abstract class Document{ 
    protected List<Page> _pages = new List<Page>(); 

    // Constructor calls abstract Factory method 
    public Document(){} 

    public List<Page> Pages 
    { 
     get { CreatePages(); return _pages; } 
    } 

    // Factory Method 
    protected abstract void CreatePages(); 
} 

class Resume : Document{ 
    // Factory Method implementation 
    protected override void CreatePages(){ 
     if(pages.Count == 0){ 
     _pages .Add(new SkillsPage()); 
     _pages .Add(new EducationPage()); 
     _pages .Add(new ExperiencePage()); 
     } 
    } 
} 

संपादित सुझाव: मैं व्यक्तिगत रूप के रूप में यह आप मुसीबत में पड़ सकता है कई तरीके और धागे के बीच साझा किया है कि वैश्विक _pages चर होने पसंद नहीं है। मैं गोफ बुक में वर्णित कारखाने विधि पैटर्न के लिए जाना चाहूंगा।

abstract class Document{ 
    public IEnumerable<Page> Pages{ 
     get { return CreatePages();} 
    } 

    // Factory Method 
    protected abstract IEnumerable<Page> CreatePages(); 
} 

class Resume : Document{ 
    // Factory Method implementation 
    protected override IEnumerable<Page> CreatePages(){ 
     List<Page> _pages = new List<Page>(); 
     _pages .Add(new SkillsPage()); 
     _pages .Add(new EducationPage()); 
     _pages .Add(new ExperiencePage()); 
     return _pages; 
     } 
    } 
} 
+0

यह 'पन्ने' की प्रत्येक पहुंच पर पृष्ठों को जोड़ना जारी रखेगा। मुझे लगता है कि 'पन्ने' प्रॉपर्टी के अंदर आप जांचेंगे कि क्या _ _pages == null' है और केवल 'CreatePages'' को कॉल करें। – comecme

+0

@comecme बस मेरे कोड को अपडेट किया गया :) यह ठीक होना चाहिए – GETah

+1

आपका कोड समझ में नहीं आता है, 'CreatePages() 'में शून्य वापसी है, तो' myResume.Pages' मुझे इस डिज़ाइन में क्या देता है? – EkoostikMartin

1

मेरे सवाल यह है कि आप अभी भी फैक्ट्री पैटर्न का उपयोग करने के लिए इस refactor कर सकते हैं है, लेकिन निर्माता में आभासी सदस्य कॉल के बिना: यहाँ मेरी सुझाव है।

परिभाषा

वर्ग आधारित प्रोग्रामिंग में के अनुसार, कारखाने विधि पैटर्न एक creational पैटर्न वस्तु की सही वर्ग निर्दिष्ट किए बिना जो कारखाने तरीकों का उपयोग करता वस्तुओं बनाने की समस्या से निपटने के लिए है कि उत्पन्न होगा।

फैक्टरी विधि का उद्देश्य कन्स्ट्रक्टर से उपयोग नहीं किया जाना चाहिए, क्योंकि वस्तु के सटीक वर्ग को निर्माण समय पर जाना जाता है। उदाहरण के लिए,

  1. अगर Document निर्माण समय में सभी Pages बनाना चाहिए, तो यह यह कारखाना विधि के बिना कर सकते हैं, क्योंकि यह जानता है कि वास्तव में पेज बनाया जा करने के लिए सभी

  2. लेकिन अगर DocumentPages बाद में बनाना चाहिए निर्माण और हो सकता है कई बार के बाद, तो कारखाने पद्धति उपयोगी है

मैं भी बहुत कुछ situat पसंद करते हैं आयन जहां एक नया रेज़्यूमे बनाना वास्तव में पृष्ठों को फिर से शुरू करने के लिए आवश्यक है।

तो, अगर सब Pages निर्माण समय पर बनाए जा सकने कर रहे हैं, यह ठोस उदाहरण कारखाने विधि पैटर्न के उपयोग के बिना फिर से लिखा जा सकता है:

public class Document 
    private readonly PageList as IList(of IPage) 

    public readonly property Pages as IEnumerable(of IPage) 
     get 
      return PageList 
     end get 
    end property 

    public sub new() 
     Me.PageList = new List(of IPage) 
    end sub 

    protected sub Add(paramarray Pages() as IPage) 
     Me.Pages.AddRange(Pages) 
    end sub 
end public 

public class Resume 
    inherits Document 

    public sub new() 
     mybase.add(new SkillsPage, new EducationPage, new ExperiencePage) 
    end sub 
end class 
  1. विधि Add से इस्तेमाल किया जा करने की अनुमति है Resume कन्स्ट्रक्टर, Document ऑब्जेक्ट पूरी तरह से निर्मित और उपयोग करने के लिए तैयार है।

  2. विधि Add संरक्षित है, इसलिए पृष्ठों को केवल Document या व्युत्पन्न कक्षाओं से जोड़ा जा सकता है।

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