2010-08-26 18 views
5

मुझे एक कठिन समय लग रहा है कि एक डीटीओ मैपर में फैक्ट्री पैटर्न को कैसे कार्यान्वित किया जाए, जिसे मैं बनाने की कोशिश कर रहा हूं। मुझे यकीन है कि मुझे अपने डिजाइन पर पुनर्विचार करने की ज़रूरत है। यहाँ है कि मैं क्या करने के लिए चल रहा हूँ का एक बहुत छोटा उदाहरण है:कास्टिंग और फैक्टरी पैटर्न टाइप करें

public abstract class Person 
{ 
    public string Name { get; set; } 
    public decimal Salary { get; set; } 
} 

public class Employee : Person 
{ 
    public Employee() 
    { 
     this.Salary = 20000; 
    } 

} 

public class Pilot : Person 
{ 
    public string PilotNumber { get; set; } 

    public Pilot() 
    { 
     this.Salary = 50000; 
    } 
} 

public static class PersonFactory 
{ 
    public static Person CreatePerson(string typeOfPerson) 
    { 
     switch (typeOfPerson) 
     { 
      case "Employee": 
       return new Employee(); 
      case "Pilot": 
       return new Pilot(); 
      default: 
       return new Employee(); 
     } 
    } 
} 

और कारखाने का उपयोग करने के: मैं कैसे चारों ओर यह पायलट को typecasting बिना पायलट संख्या लोड हो रहा है मिलता है

Person thePilot = PersonFactory.CreatePerson("Pilot"); 
     ((Pilot)thePilot).PilotNumber = "123ABC"; 

? ? क्या यह करने का गलत तरीका है? मैं पायलट नंबर को व्यक्ति वर्ग में डाल सकता हूं, लेकिन फिर कर्मचारी संख्या का उत्तराधिकारी होगा और यही वह नहीं है जो मैं चाहता हूं। मैं क्या कर सकता हूँ?

धन्यवाद!

-Jackson

+0

बस "डीटीओ मैपर" शब्द का जवाब देना: http: //automapper.codeplex।कॉम/ –

+0

धन्यवाद! यह सहायक था! – adminJaxon

उत्तर

9

आप अपने PersonFactory वर्ग के लिए विशिष्ट प्रकार के तरीके जोड़ सकता है, या एक सामान्य CreatePerson<T>() विधि जोड़ने के लिए, लेकिन यह है कि केवल फोन करने वाले अगर उपयोगी होगा पहले से ही जानता है कि यह किस प्रकार का व्यक्ति प्राप्त करना चाहिए। शायद यह मामला है, या शायद नहीं।

इस परिदृश्य के साथ, मैं उम्मीद करता हूं कि कोड वास्तव में व्यक्ति को कॉल करने के लिए कॉल कर रहा है। क्रेतेपर्सन को पता नहीं होगा कि किस तरह का व्यक्ति वापस आ रहा है। यदि आपके पास उस बिंदु के बाद कुछ कोड है जो पहले से जानता है या आंकड़े करता है कि आपके पास किस प्रकार का व्यक्ति है, तो आपको बस इसे डालना होगा।

नीचे एक कोड उदाहरण है जो दिखाता है कि आप अपने कारखाने और विभिन्न उपयोग परिदृश्यों पर क्या कर सकते हैं, यह समझाने का प्रयास करते हैं कि आपको केवल कब डालने की आवश्यकता है या जब आप नहीं करते हैं।

public static class PersonFactory 
{ 
    public static Person CreatePerson() 
    { 
     return new Person(); 
    } 

    public static Employee CreateEmployee() 
    { 
     return new Employee(); 
    } 

    public static Pilot CreatePilot() 
    { 
     return new Pilot(); 
    } 

    public static T CreatePerson<T>() 
     where T : Person 
    { 
     return (T)CreatePerson(typeof(T)); 
    } 

    public static Person CreatePerson(Type type) 
    { 
     if (type == typeof(Person)) 
      return CreatePerson(); 
     else if (type == typeof(Employee)) 
      return CreateEmployee(); 
     else if (type == typeof(Pilot)) 
      return CreatePilot(); 
     else 
      throw new ArgumentOutOfRangeException(string.Format(CultureInfo.InvariantCulture, "Unrecognized type [{0}]", type.FullName), "type"); 
    } 

    public static Person CreatePerson(string typeOfPerson) 
    { 
     switch (typeOfPerson) 
     { 
      case "Employee": 
       return CreateEmployee(); 
      case "Pilot": 
       return CreatePilot(); 
      default: 
       return CreateEmployee(); 
     } 
    } 
} 



class UsageExample 
{ 
    Person GetPerson() 
    { 
     Pilot p; 
     p = (Pilot)PersonFactory.CreatePerson("Pilot"); // this code already knows to expect a Pilot, so why not just call CreatePilot or CreatePerson<Pilot>()? 
     p = PersonFactory.CreatePilot(); 
     p = PersonFactory.CreatePerson<Pilot>(); 
     return p; 
    } 

    Person GetPerson(Type personType) 
    { 
     Person p = PersonFactory.CreatePerson(personType); 
     // this code can't know what type of person was just created, because it depends on the parameter 
     return p; 
    } 

    void KnowledgableCaller() 
    { 
     Type personType = typeof(Pilot); 

     Person p = this.GetPerson(typeof(Pilot)); 
     // this code knows that the Person object just returned should be of type Pilot 

     Pilot pilot = (Pilot)p; 
     // proceed with accessing Pilot-specific functionality 
    } 

    void IgnorantCaller() 
    { 
     Person p = this.GetPerson(); 
     // this caller doesn't know what type of Person object was just returned 

     // but it can perform tests to figure it out 
     Pilot pilot = p as Pilot; 
     if (pilot != null) 
     { 
      // proceed with accessing Pilot-specific functionality 
     } 
    } 
} 
+0

मुझे IgnoarantCaller विधि पसंद है। मैं इसका उपयोग करने में सक्षम हो सकता हूं! मैं एक टेबल से रिकॉर्ड्स का एक गुच्छा लोड कर दूंगा प्रति पारा तालिका प्रति पदानुक्रम। यदि व्यक्ति के पास "पर्सोट टाइप" कॉलम में "पायलट" है, तो पायलट तालिका से पायलट नंबर लोड करें। यदि पंक्ति में व्यक्ति के प्रकार में "कर्मचारी" प्रकार है, तो पायलट लोड न करें संख्या .. – adminJaxon

12

कारखाने पैटर्न सबसे अच्छा प्रयोग किया जाता है जब वस्तुओं कार्यान्वयन में मतभेद है, इंटरफेस नहीं। आपके मामले में कारखाना पैटर्न बहुत फायदेमंद नहीं है, और आप शायद अपनी वस्तुओं को सीधे बनाने (या कुछ अन्य पैटर्न शायद बेहतर) बनाने से बेहतर हैं।

+0

क्या आप इसे थोड़ा और अधिक @ मैट ग्रीर पर विस्तारित कर सकते हैं? 'ऑब्जेक्ट्स कार्यान्वयन में भिन्न हैं, इंटरफ़ेस नहीं' -> इस मामले पर यह कैसे लागू होता है? –

+2

@Zortkun यह लागू होता है क्योंकि केवल पायलटों में 'पायलट नम्बर 'होता है। तो इसे स्थापित करने का एकमात्र तरीका कारखाने के उद्देश्य को हराकर एक कलाकार के साथ है। –

1

क्या आप हैं जो आपके इच्छित प्रकार को संवाद करने के लिए स्ट्रिंग का उपयोग करने के लिए करते हैं? आप जेनरिक बजाय इस्तेमाल कर सकते हैं:

public static T CreatePerson<T>() where T : Person 

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

public static T CreatePerson<T>() where T : Person, new() 
{ 
    return new T(); 
} 

हालांकि, वह भी काफी व्यर्थ फोन करने वाले के बजाय कर सकता है के रूप में है। क्या आपकी वास्तविक स्थिति में जेनेरिक व्यवहार्य है? यदि नहीं, तो क्या आप समझा सकते हैं क्यों नहीं, और हम इसके आसपास काम करने की कोशिश कर सकते हैं?

+0

जेनिक्स इस मामले में काम कर सकते हैं। मैं मूल रूप से एक डेटाबेस तालिका है कि मेरे पास प्रति प्रकार पदानुक्रम तालिका है। आइए एक "पर्सन टाइप" फ़ील्ड के साथ एक व्यक्ति जगह कहें। और "पायलट" विशिष्ट जानकारी के साथ एक और तालिका। लोगों का परिणाम सेट प्राप्त करने के लिए यदि डेटाबेस पंक्तियों की सूची के माध्यम से पुनरावृत्ति होगी, यदि यह "पायलट" प्रकार है, तो पायलट तालिका की जानकारी लोड करें, यदि यह "कर्मचारी" प्रकार उस विशिष्ट जानकारी को लोड करता है। लेकिन डीओएन "कर्मचारी वस्तुओं में टी लोड पायलट सामान ... क्या इससे थोड़ा और स्पष्ट हो जाता है? धन्यवाद! – adminJaxon

1

इसके आसपास कोई आसान तरीका नहीं है।

पायलट नम्बर संपत्ति का उपयोग करने के लिए आपको पायलट प्रकार की आवश्यकता है। फैक्ट्री पैटर्न का उपयोग करना मतलब है कि आप अलग-अलग उप-प्रकार के व्यक्ति को छोड़ रहे हैं।

समान पैटर्न अगर यह किसी भी सांत्वना है, बीसीएल है,

var req = WebRequest.CreateRequest("http://someUrl"); 
((HttpWebRequest)req).Contentlenght = ...; 
संबंधित मुद्दे