2014-05-21 4 views
10

मैं राज्य डिजाइन पैटर्न में नया हूं और मुझे किसी ऑब्जेक्ट के विभिन्न राज्यों को डेटाबेस (मेरे मामले में SQL सर्वर) को सहेजने का उचित उदाहरण नहीं मिल रहा है। निम्नलिखित आलेख में वर्णित उदाहरण के लिए परिदृश्य काफी समान [लगभग समान] है, हालांकि मुझे डेटाबेस को राज्यों के लिए जारी रखने के लिए एक लागू समाधान नहीं मिला है। क्या आप लोग एक लिंक की सिफारिश कर सकते हैं या संभवतः एक उदाहरण दे सकते हैं?राज्य पैटर्न को लागू करने वाली वस्तुओं को कैसे बनाए रखें?

State Pattern Usage and Sample in C#

इसके अलावा: यदि आप रन टाइम पर सभी विभिन्न ConcreteState प्रकार कैसे की गणना करते हैं? उदाहरण के लिए, यदि आपके पास 10 अलग-अलग राज्य हैं, तो क्या आप 10 अलग-अलग सदस्यों के साथ एनमस्टेट्स घोषित करते हैं और प्रत्येक एकल कंक्रीटस्टेट सदस्य को एक संबद्ध एनमस्टेट्स सदस्य देते हैं, या आपको कंक्रीटस्टेट के उप-वर्ग प्राप्त करके सभी विशिष्ट राज्य मिलते हैं?

आपके लिए जानकारी के लिए, मुझे अपने विभिन्न राज्यों के आधार पर इकाइयों की खोज करने में सक्षम होना चाहिए।

+0

आपका लिंक टूटा हुआ है। – Tanner

उत्तर

7

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

  • प्रत्येक राज्य वर्ग को एक सदस्य मूल्य प्रदान करता है जो राज्य के लिए अद्वितीय है।
  • जब आप उस वस्तु को बनाए रखते हैं जिसमें राज्य है, तो Enum को बनाए रखें।

राज्य वापस

  • प्राप्त करने के लिए जब आप वस्तु लोड करते हैं, या तो

    • इन्स्तांत वस्तु के राज्य तुरंत सदस्य और वस्तु के राज्य सदस्य के लिए असाइन करें, या यदि वह किसी राज्य का दृष्टांत को महंगा है , किसी विधि के माध्यम से राज्य सदस्य तक पहुंचने के लिए ऑब्जेक्ट को बदलें और राज्य पहचान एनम सदस्य के मूल्य के आधार पर राज्य को आलसी ढंग से उस विधि में तत्काल स्थापित करें।

    किसी भी तरह से, आपको एक एनम मूल्य से राज्य में जाने में सक्षम होना चाहिए। ऐसा तब तक करें जब तक आप उस पहचान मूल्य से मेल नहीं खाते, तब तक सभी प्रासंगिक राज्य वर्गों के माध्यम से लूप करके।

    तो, प्रासंगिक राज्य क्या हैं? यह इस बात पर निर्भर करता है कि राज्य वर्ग कौन लिख रहा है।

    • सरल मामले में, जहां आप पूरे कार्यक्रम और कार्यक्रम में राज्य कक्षाओं के सभी पर नियंत्रण में संभावित राज्य होने वस्तु के सदस्य हैं, आप कर सकते हैं बस सभी उपवर्गों या राज्य के कार्यान्वयन से अधिक पाश सुपरक्लास या इंटरफ़ेस, इस तरह: Getting all types that implement an interface

    • यदि किसी कारण से राज्य कक्षाएं हैं जिन्हें आप लूप नहीं करना चाहते हैं, तो बस उन लोगों की एक सूची परिभाषित करें जिन्हें आप निरंतर लूप करना चाहते हैं या (यदि आप इसे बदले बिना बदलना चाहते हैं कोड) विन्यास में।

    तो राज्य वर्गों की अपनी सूची बना रही है धीमी है, सिर्फ कार्यक्रम स्टार्टअप या पहले प्रयोग एक ही बार में करते हैं। यदि आप सूची को हार्डकोड करते हैं, तो राज्य-वर्ग वर्ग (यह विशिष्ट राज्यों से स्वतंत्र होना चाहिए) या राज्य सुपरक्लास में ऐसा न करें (जो एक परिपत्र निर्भरता पेश करेगा); अपने कार्यक्रम में सूची (या फराहद सुझाव के रूप में) में अपनी सूची में उच्च (निर्भरता-वार) सूची डालें।

    There are a lot of examples how how to persist objects with State out there; this one अपेक्षाकृत सरल है।

  • 1

    मैं उस बिंदु तक डेव के उत्तर से सहमत हूं जहां आपको ऑब्जेक्ट लोड करते समय राज्य प्राप्त करने की आवश्यकता होती है। मुझे नहीं लगता कि हमेशा सभी राज्य वर्गों या कक्षाओं की एक सूची के माध्यम से इसे लागू करना एक अच्छा विचार है जब आपके पास राज्यों की कई अलग-अलग वस्तुएं होती हैं।

    मुझे लगता है कि स्थिति में लगता है कि एक StateManager वर्ग जो भी राज्यों Enum परिभाषा और भी प्रत्येक Enum मूल्यों और उसकी State वस्तु (Dictionary<StateEnum, State>) के बीच एक मैपिंग हो सकती है होना चाहिए। यह मैपिंग या तो हार्ड-कोड किया जाना चाहिए या कॉन्फ़िगरेशन फ़ाइल से पढ़ना चाहिए। यह वर्ग राज्यों की आलसी लोडिंग को संभालने में सक्षम हो सकता है जब उन्हें पहली बार एक्सेस किया जा रहा है। यह उन्हें Singleton ऑब्जेक्ट्स के रूप में भी बना सकता है यदि राज्य में वास्तव में फ़ील्ड नहीं हैं बल्कि कार्यक्षमताएं हैं (जैसे ओपी के सबमिशन में लिंक लिंक में)।

    4

    राज्यों को तालिका में स्तंभों में अनुवाद करने का प्रयास न करें, जो काम नहीं करेंगे।

    इसके बजाय JSON.NET का उपयोग कर राज्यों को क्रमबद्ध करें क्योंकि यह विरासत का समर्थन करता है। तब की तरह एक तालिका में संग्रहीत: यदि आप चाहते हैं, लेकिन

    create table OrderStates 
    (
        OrderId int not null, 
        Data nvarchar(MAX) not null 
    ); 
    

    अधिक स्तंभ शामिल केवल कॉलम जो पहचान करने के लिए क्या राज्यों के लिए उपयोग किया जाता है की आवश्यकता है।

    JSON.NET में विरासत समर्थन आप उपयोग करने के लिए सक्रिय करने के लिए:

    var json = JsonConvert.SerializeObject(yourState, typeof(StateBaseClass), JsonConvert.DefaultSettings)`. 
    using (var cmd = sqlConnection.CreateCommand()) 
    { 
        cmd.CommandText = "INSERT INTO OrderStates (OrderId, Data) VALUES(@OrderId, @Data)"; 
        cmd.Parameters.AddWithValue("OrderId", orderId); 
        cmd.Parameters.AddWithValue("Data", json); 
        cmd.ExecuteNonQuery(); 
    } 
    

    ही चला जाता है जब deserializing, जब JsonConvert.DeserializeObject() का उपयोग कर आधार वर्ग निर्दिष्ट करें।

    आप रन टाइम पर सभी अलग कंक्रीटस्टेट प्रकारों का आकलन कैसे करते हैं? उदाहरण के लिए, यदि आपके पास 10 अलग-अलग राज्य हैं, तो क्या आप 10 अलग-अलग सदस्यों के साथ एनमस्टेट्स घोषित करते हैं और प्रत्येक एकल कंक्रीटस्टेट सदस्य को एक संबद्ध एनमस्टेट्स सदस्य देते हैं, या आपको कंक्रीटस्टेट के उप-वर्ग प्राप्त करके सभी विशिष्ट राज्य मिलते हैं?

    सबक्लास। यह अन्य राज्यों को संशोधित किए बिना नए राज्यों को पेश करने या पुराने लोगों को हटाने में सक्षम होने का एकमात्र तरीका है। मौजूदा वर्गों में से प्रत्येक संशोधन बग पेश कर सकता है।

    +0

    नीचे वोट की व्याख्या करने के लिए देखभाल? – jgauffin

    2

    मैं, उदाहरण आप लिंक किए गए पसंद नहीं आया नीचे मैं कारणों को सूचीबद्ध:

    1. मैं मानता हूँ कि बने वास्तुकला एक मेस होगा - मेरी राय में गंदा करने के लिए जिस तरह से।
    2. प्रति राज्य नया उदाहरण बनाना मुझे दक्षता आत्मघाती पैटर्न की तरह लगता है।
    3. परीक्षण नरक होगा ... त्रुटियों को ढूंढना नरक होगा .. डिबगिंग नरक होगा।
    4. अनुभव के 30 से अधिक वर्षों में मैंने कभी भी इस पैटर्न को डेटा केंद्रित अनुप्रयोग में कभी भी इस्तेमाल नहीं किया - मैंने इसे देखा और उन मामलों में इसका इस्तेमाल किया जहां मुझे जानकारी जारी रखने की आवश्यकता नहीं है, उदाहरण के लिए जब नेटवर्क परत बनाना - प्रति बंदरगाह के साथ इस बंदरगाह का इलाज किया जा सकता है।


    मैं बजाय इस पैटर्न के लिए जाना होगा:

    पैटर्न बुनियादी ढांचे कुछ छद्म आदेश वस्तु के लिए

    public interface IStateObject<T> 
    { 
        T State { get; set; } 
        void Process(); 
    } 
    

    उदाहरण कार्यान्वयन

    public enum OrderState 
    { 
        Taken, 
        Approved, 
        Payed, 
        Emailed, 
        BeforeShipment 
        //etc.. etc.. 
    } 
    
    public class Order : IStateObject<OrderStates> 
    { 
        //some linear fields of order.. 
        //: name, description, etc.. etc.. 
    
        public OrderStates State { get; set; } 
    
        public void Process() 
        { 
         switch (State) 
         { 
          case OrderState.Taken: 
           // code to handle this state 
           break; 
          case OrderState.Approved: 
           // etc.. 
           break; 
          } 
         //persist myself to db. 
        } 
    } 
    

    यह बहुत आसान है क्योंकि आप वस्तु के प्रति संदर्भ प्रति पंक्ति को एक पंक्ति में सहेज सकते हैं।
    इसके अलावा एक ऑब्जेक्ट एक बार बनाया गया है जैसा कि हमारे पास हमारे पास कोई कंप्यूटर नहीं था ..
    लेकिन अधिकतर क्योंकि यह बहुत सीधी और बहुत लचीला है।

    आप आप वास्तव में नोटिस की जरूरत नहीं हो सकता है हो सकता है IStateObject<T> बिल्कुल - लेकिन मैं बहस आप इसे बाद में जब आप खड़ी निर्णयों पर कार्रवाई करने के लिए चाहते हैं पर की आवश्यकता होगी होगा। ध्यान रखें कि T को enum होना आवश्यक नहीं है। यह आपकी ऐप जरूरतों के अनुसार विकसित होने के लिए सामान्य आधार के रूप में काम कर सकता है।

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

    पैटर्न इस जवाब में की पेशकश का उपयोग करना - आप जोड़ना एक पिछली ऑर्डरस्टेट संपत्ति और अब आपके पास प्रति पंक्ति इतिहास है .. और अन्य तरीकों से मुझे यकीन है कि आप सोच सकते हैं ..

    लेकिन "राज्य पैटर्न" का उपयोग करके - आप गंभीर समस्या में होंगे ... यह होगा वास्तव में ऐसा करने के लिए एक पूर्ण "पैमाने स्तर" द्वारा जटिल होने जा रहा है .. आपको प्रत्येक प्रकार की तालिका से प्रत्येक प्रकार की अन्य तालिका में लिंक करने में सक्षम होना होगा - या tr y आपके डेटाबेस पर ऑब्जेक्ट ओरिएंटेड बल को मजबूर करने के लिए ...

    मेरा मुद्दा देखें? राज्य पैटर्न केवल डेटा केंद्रित ऐप्स के लिए डिज़ाइन नहीं किया गया है।

    गुड लक।

    +1

    यह बिल्कुल राज्य डिजाइन पैटर्न नहीं है। जबकि कुछ मामलों में एक स्विच-केस सही जवाब हो सकता है, मुझे नहीं लगता कि आपको दृढ़ता के मुद्दों के कारण इसे वापस गिरना चाहिए। आम तौर पर, राज्य-पैटर्न आपको जटिल मामलों में एक मीट्रिक टन बग बचा सकता है। – Gilthans

    +0

    @ गिलथन्स मैं आपकी टिप्पणी से सहमत हूं। लेकिन आदेश राज्य एक अलग संदर्भ नहीं है जो प्रति मामले वस्तु को औचित्य देता है। ऑर्डर-स्टेट ऑर्डर की एक संपत्ति है। एक हरे रंग की व्यक्ति की तरह एक अलग प्रकार का व्यक्ति नहीं होता है - केवल एक अलग प्रकार की संपत्ति किसी व्यक्ति से संबंधित होती है .. यह गुण करना महत्वपूर्ण है कि गुण क्या हैं और दो अलग-अलग वस्तुएं क्या हैं। 'ऑर्डर' एक ऑब्जेक्ट प्रकार है क्योंकि इसे स्वयं को मूर्त रूप देने के लिए किसी और चीज की आवश्यकता नहीं है - 'ऑर्डर-स्टेट' एक संपत्ति है क्योंकि यह ऑर्डर के बिना पूरा नहीं कर सकता है। –

    +0

    या तो विकल्प प्रोग्राम के लिए एक वैध तरीका है; किसी भी मामले में ऑर्डर-स्टेट ऑर्डर की एक संपत्ति है, लेकिन यह एक enum हो सकता है जो आदेश में हेरफेर करता है, या यह एक वस्तु हो सकती है जो स्वयं को कुशल बनाती है। उत्तरार्द्ध अधिक ओओपी-आश है, और आम तौर पर अनमोल संयोजनों के कारण बगों से कम प्रवण होता है। मुझे यहां दिया गया उदाहरण पसंद है: http://gameprogrammingpatterns.com/state.html – Gilthans

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