2011-08-08 10 views
9

एक आवेदन जो मैं प्रक्रियाओं पर काम कर रहा हूं कार्य आइटम। एक कार्य आइटम की स्थिति के आधार पर कई क्रियाएं उपलब्ध हैं। "पूर्ण" "रद्द करें" "पुन: असाइन करना" आदि ...एक डिजाइन पैटर्न की सिफारिश करें

कार्यों मैं वर्तमान में एक अंतरफलक है कि कुछ इस तरह दिखता है के लिए कार्यक्षमता प्रदान करने के लिए ...

public interface IActionProvider{ 
    public void Complete(WorkItem workItem); 
    public void Cancel (WorkItem workItem); 
    public void Reassign(WorkItem workItem); 
} 

तब के अन्य विवरणों के आधार पर कार्य आइटम में इंटरफेस के ठोस कार्यान्वयन हैं। बस उदाहरण के लिए ...

public class NormalActionProvider :IActionProvider 
{ 
    ... 
} 

और

public class UrgentActionProvider : IActionProvider 
{ 
    .... 
} 

समस्या यह है, अगर मैं किसी नए कार्य जोड़ना चाहते हैं, कहते हैं ... "प्रतिनिधि" मैं इंटरफ़ेस अपडेट करना पड़ता है जो निश्चित रूप से सभी कार्यान्वयन पर प्रभाव पड़ता है।

क्या यह ओपन/क्लोज़ सिद्धांत का उल्लंघन करता है? क्या आप एक डिजाइन पैटर्न या रिफैक्टर की सिफारिश कर सकते हैं जो मेरी मदद कर सकता है?

उत्तर

11

ऐसा लगता है कि कमांड पैटर्न उपयुक्त होगा। आप अधिक आदेश संशोधित/जोड़ सकते हैं। कमांड वर्ग मुख्य कार्यक्रम से decoupled हैं।

public interface IActionProvider{ 
    public void execute(WorkItem item,ActionType actionType); 
} 

ActionType पूरा प्रतिनिधित्व करता है, & इतने पर रद्द। आप अधिक क्रिया प्रकार & प्लगइन उचित कमांड कक्षाओं को जोड़ना जारी रख सकते हैं।

0

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

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

3

आप हमेशा IActionProvider इंटरफ़ेस में एक सजावट जोड़ सकते हैं (Decorator design pattern का पालन करें)।

0

"workitem की स्थिति पर निर्भर करता है", राज्य डिजाइन पैटर्न

एक तरह से पेश करती है या किसी अन्य के लिए, आप आप इंटरफेस और अंत में ग्राहक अनुबंध तोड़ने refactor करना होगा।

यदि मैं आपकी समस्या को सही ढंग से समझ गया हूं, तो आपके पास वर्कइटम प्रोसेसर है जिसका राज्य पर भेजे गए वर्कइटम पर निर्भर करता है।

इसलिए अपने WorkItemProcessor

// Context 
    public class WorkItemProcessor 
    { 
     public IState CurrentState { get; set; } 

     public WorkItemProcessor(IState initialState) 
     { 
      CurrentState = initialState; 
     } 

     public void Process(WorkItem workItem) 
     { 
      CurrentState.Handle(this, workItem); 
     } 
    } 

फिर हम कि WorkItemProcessor संभावित मान लिया जाये कि अपने WorkItem लगता

// Request 
    public class WorkItem 
    { 
     public bool CompletenessConditionHoldsTrue { get; set; } 

     public bool CancelConditionHoldsTrue { get; set; } 
    } 

की तरह यह सब कहें

// State Contract 
    public interface IState 
    { 
     void Handle(WorkItemProcessor processor, WorkItem item); 
    } 

    // State One 
    public class CompleteState : IState 
    { 
     public void Handle(WorkItemProcessor processor, WorkItem item) 
     { 
      processor.CurrentState = item.CompletenessConditionHoldsTrue ? (IState) this : new CancelState(); 
     } 
    } 

    // State Two 
    public class CancelState : IState 
    { 
     public void Handle(WorkItemProcessor processor, WorkItem item) 
     { 
      processor.CurrentState = item.CancelConditionHoldsTrue ? (IState) this : new CompleteState(); 
     } 
    } 

में हो सकता है कई राज्यों को परिभाषित हो जाता है एक साथ

static void Main() 
    { 
     // Setup context in a state 
     WorkItemProcessor processor = new WorkItemProcessor(new CancelState()); 

     var workItem1 = new WorkItem { CompletenessConditionHoldsTrue = true }; 
     var workItem2 = new WorkItem { CancelConditionHoldsTrue = true }; 

     // Issue requests, which toggles state 
     processor.Process(workItem1); 
     processor.Process(workItem2); 

     Console.Read(); 
    } 

आशा है कि यह आपको करीब ले जाएगा। चीयर्स।

0

मैं कमांड पैटर्न भी चुनूंगा। एक वृद्धि के रूप में, आप इसे अमूर्त फैक्ट्री विधि के साथ जोड़ सकते हैं, ताकि आप प्रत्येक कमांड क्लास के लिए फैक्ट्री क्लास रख सकें, और उन सभी कारखानों में एक आम फैक्ट्री इंटरफ़ेस लागू होता है।

उदाहरण के लिए:

// C# 
public interface ICommand { void Execute(); } 

public interface ICommandFactory { ICommand Create(); } 

public class CommandFactoryManager 
{ 
    private IDictionary<string, ICommandFactory> factories; 

    public CommandFactoryManager() 
    { 
     factories = new Dictionary<string, ICommandFactory>(); 
    } 

    public void RegisterCommandFactory(string name, ICommandFactory factory) 
    { 
     factories[name] = factory; 
    } 

    // ... 
} 

इस तरह, आप नए आदेश कारखानों गतिशील रजिस्टर कर सकते हैं। उदाहरण के लिए, आप रनटाइम पर एक डीएलएल लोड कर सकते हैं और प्रतिबिंब का उपयोग कर आईसीओएमएंड फैक्ट्री इंटरफ़ेस को लागू करने वाले सभी वर्गों को प्राप्त कर सकते हैं, और आपके पास एक साधारण प्लगइन सिस्टम है।