2012-02-23 41 views
1

我有一個情況,我有8個步驟(把它想象成一個嚮導)。每一步都有不同的東西,所以我創建了8個類。每個類都需要前面步驟(類)的一些信息。所有類都從一個主類中調用。該neatiest方式我發現來處理這種情況是:如何引用多個類而不會造成混亂?

public void Main() 
{ 
    var step1 = new Step1(); 
    step1.Process(); 
    var step2 = new Step2(step1); 
    step2.Process(); 
    var step3 = new Step3(step1, step2); 
    //... 
    var step8 = new Step8(step1, step2, step3, step4, step5, step6, step7); 
    step8.Process(); 
} 

顯然,這是一個爛攤子。我不想發送那麼多參數,我不想使用靜態類(可能不是一個好習慣)。

你會如何處理這種情況?

+1

是在單獨的.cs文件在您的類或嵌套在一個單一命名空間..?我只是做了一些與你正在談論的內容相近的東西,並且我在一個或兩個類中創建了Auto屬性,並使用傳遞/分配步驟的巧妙方法,並且它看起來非常乾淨,可以顯示類名稱/結構的樣子。 – MethodMan 2012-02-23 20:28:00

+0

相同的命名空間,但不同的.cs文件 – Mathieu 2012-02-23 20:28:50

+2

責任鏈模式? – 2012-02-23 20:29:57

回答

8

這聽起來像是我可以通過Chain of Responsibility Pattern完成的事情。這是我至少會研究的方向。

如果你沿着這條道路走下去,那麼你將會對未來增加/刪除步驟的更清晰的實現敞開大門。

而且,就多個數據集而言,John Koerner是正確的,因爲您應該有一個在每個步驟中更新的數據模型。這將使您能夠實施清潔的責任鏈。

3

有一個類是您的數據模型,可以在整個流程中使用。這些步驟更新它們的數據模型片段,並且這是傳遞給每個後續步驟的唯一對象。

1

只創建一個類,並使用不同的方法與步驟

class Wizard 
{ 
    int someIntInfo; 
    string some StringInfo; 
    ... 

    public void ProcessStep1(); 
    public void ProcessStep2(); 
    public void ProcessStep3(); 
    public void ProcessStep4(); 
} 

或者創建一個步驟和信息接口,並通過將相同的信息給所有申報這樣的嚮導步驟

interface IWizardInfo 
{ 
    int someIntInfo { get set; } 
    string someStringInfo { get set; } 
    ... 
} 

interface IStep 
{ 
    void Process(IWizardInfo info); 
} 

class Wizard 
{ 
    IWizardInfo _info = ....; 
    IStep[] _steps = new IStep[] { new Step1(), new Step2(), ... }; 
    int _currentStep; 

    void ProcessCurrentStep() 
    { 
     _steps[_currentStep++].Process(_info); 
    } 
} 

編輯:

建立可容納所有以前的一種化合物類步驟

class Step1 { public Step1(AllSteps steps) { steps.Step1 = this; } ... } 
class Step2 { public Step2(AllSteps steps) { steps.Step2 = this; } ... } 
class Step3 { public Step3(AllSteps steps) { steps.Step3 = this; } ... } 

class AllSteps 
{ 
    public Step1 Step1 { get; set; } 
    public Step2 Step2 { get; set; } 
    public Step3 Step3 { get; set; } 
} 

將相同的信息傳遞給所有步驟。步驟有責任將自己添加到信息

AllSteps allSteps = new AllSteps(); 
var stepX = new StepX(allSteps); 
+0

如果我有更少的子步可能會很好。在這種情況下,它會創建一個具有幾十個屬性的3-4k行文件 – Mathieu 2012-02-23 20:32:36

+0

添加了一個解決方案,它基本上可以完成您最初的工作;但是,不是將所有步驟逐一作爲參數傳遞,而是使用將所有步驟放在一起的類。 – 2012-02-23 21:02:14

0

爲什麼不創建爲您的所有步驟,一個單一類和類中實現狀態管理?例如

private class Steps 
{ 
    private int _stepIndex = 0; 
    public void Process() 
    { 
     switch(_stepIndex) 
     { 
      case 0: // First Step 
      ... // Perform business logic for step 1. 
      break; 
      case 1: // Second Step 
      ... // Perform business logic for step 2. 
      break; 
     } 
     _stepIndex++; 
    } 
} 
+0

當步驟很簡單時,這很好。然而,在更大的步驟上,這變得難以管理。 – Mathieu 2012-02-23 20:33:49

1

似乎Java的內部類比C#更適合這個。但是,C#在很多其他方面都好得多,我們會讓這個通過。

您應該創建一個包含所有數據的類。如果你的步驟很簡單,那麼你應該有一個方法的每個步驟。如果你的步驟比較複雜,將它們分成不同的類,但是讓它們都可以訪問數據類。

1

你可以通過接口IProcess方法Run(Wizard)和屬性Name,幾個進程和每個人都繼承IProcess,並且類嚮導包含進程在列表中運行。所以:

class Wizard 
{ 
    private IList<IProcess> processes = new List<IProcess(); 

    public T GetProcess<T>(string name) 
      where T : IProcess 
    { 
     return (T)processes.Single(x => x.Name == name); 
    } 

    public void Run() 
    { 
     foreach (var proc in processes) 
       proc.Run(this); 
    } 
} 

每個進程都可以訪問使用Run方法的參數嚮導,或者只是有它在構造函數中。通過調用wizard.GetProcess<Process1>("some name"),您可以讓您的流程先前執行(您可以添加一個支票)。

其他選項是包含Wizard類中的結果。

這只是衆多變體之一。你可以看看責任鏈模式,就像Justin建議的那樣

0

我會有兩個ArrayLists(或者根據你的類和方法結構,它們可能是簡單的Lists) - 一個用於方法(作爲委託)和一個用於結果。

所以的foreach方法將經過與會代表,並與結果列表作爲參數調用它們(你可能會滿足您的方法來接受這樣parametars,並與他們的工作),並添加結果結果列表。

1

我想說的Chain-Of-Responsibility的變化的典型例子。

下面是一個例子:

class Request 
{ 
    private List<string> _data; 

    public IEnumerable<string> GetData() 
    { 
     return _data.AsReadOnly(); 
    } 

    public string AddData(string value) 
    { 
     _data.Add(value); 
    } 
} 

abstract class Step 
{ 
    protected Step _nextStep; 

    public void SetSuccessor(Step step) 
    { 
     _nextStep = step; 
    } 

    public abstract void Process(Request request); 
} 

sealed class Step1 : Step 
{ 
    public override void Process(Request request) 
    { 
     var data = request.GetData(); 

     Console.Write("Request processed by"); 
     foreach (var datum in data) 
     { 
      Console.Write(" {0} ", datum); 
     } 

     Console.WriteLine("Now is my turn!"); 

     request.AddData("step1"); 

     _nextStep.Process(request); 
    } 
} 

// Other steps omitted. 
sealed class Step8 : Step 
{ 
    public override void Process(Request request) 
    { 
     var data = request.GetData(); 

     Console.Write("Request processed by"); 
     foreach (var datum in data) 
     { 
      Console.Write(" {0} ", datum); 
     } 

     Console.WriteLine("Guess we're through, huh?"); 
    } 
} 

void Main() 
{ 
    var step1 = new Step1(); 
    // ... 
    var step8 = new Step8(); 
    step8.SetSuccessor(step1); 

    var req = new Request(); 
    step1.Process(req); 
} 
+0

不錯的例子!我會試試這個! – Mathieu 2012-02-23 20:56:21