2015-02-10 170 views
2

我正在構建一個遊戲,其中幾種方法被鏈接到其他方法,並且需要在幕後調用。例如,當一名士兵需要離開城堡,門需要打開,然後當他離開封閉:有沒有辦法避免方法調用重複?

public void MoveTheGate(bool openTheGate) 
{ 
    if (openTheGate) 
    { 
     // code for: open the gate 
    } 
    else 
    { 
     // code for: close the gate 
    } 
} 

public void GetOutOfTheCastle() 
{ 
    MoveTheGate(true); 

    // code for: get out of the castle 

    MoveTheGate(false); 
} 

這同樣適用於當來自另一個國度的使者到達城堡真,必須在使者進入城堡的開始和結束時調用方法。

有沒有一種更微妙的方法來實現這一目標?

+3

工作的代碼是題外話了StackOverflow上。你可能想看看[代碼評論](http://codereview.stackexchange.com/)。 – 2015-02-10 00:56:35

+0

這一切都取決於註釋掉的代碼是什麼。如果有一種方法可以重用它,那麼一定要保持單一的方法。 @ Pierre-LucPineault建議在Code Review上發佈完整的代碼。 – krillgar 2015-02-10 00:58:16

+1

但是,請注意Code Review不允許存根代碼。你將不得不發佈整個方法。 – Hosch250 2015-02-10 00:59:04

回答

2

你可以做

OpenGate(()=> 
    { stuff to do with gate open } 
); 

哪裏打開一扇是

public void OpenGate(Action action) 
{ 
    try 
    { 
     MoveTheGate(true); 
     action(); 
    } 
    finally 
    { 
    MoveTheGate(false); 
    } 
} 
2

這可能是矯枉過正總額,但你總是可以實現IDisposable然後用using塊。這是「確保」發生的好方法。

如果設置了一類叫上脫手某個給定的動作,

public class DelegateDisposable : IDisposable 
{ 
    private readonly Action action; 

    public DelegateDisposable(Action action) 
    { 
     this.action = action; 
    } 

    public void Dispose() 
    { 
     if(this.action != null) 
     { 
      this.action(); 
     } 
    } 
} 

然後,你可以使用這樣的:

private IDisposable OpenGate() 
{ 
    MoveTheGate(true); 
    return new DelegateDisposable(() => MoveTheGate(false)); 
} 

而且使用這樣的:

public void GetOutOfTheCastle() 
{ 
    using (OpenGate()) 
    { 
     // code for: get out of the castle 
    } 
} 

這種方法的一個很好的優點是它不會混淆你的調用堆棧,儘管它也有一些overh元首。但是,如果您將DelegateDisposable帶入某個實用程序類,它可能對其他內容也有用。

+2

雖然這確實可行,但在沒有對非託管資源進行必要的清理時,實施IDisposable會感覺很髒。 – 2015-02-10 01:02:38

+0

@DavidL這是在你對調用棧做什麼,代碼是乾淨的,還是你的原則之間的折衷。我已經看到了 - 儘管我無法想象在哪裏 - 我喜歡使用'IDisposable'來尊重這樣的項目,我不介意它太多。我認爲「門」是一種需要清理的資源,儘管我確實看到了你的觀點 - 這與開放式流或其他任何東西都不完全一樣。 – 2015-02-10 01:05:54

1

我會對繼承模式保持公正,這會強制您在基本的,繼承的抽象類的上下文中執行操作。我認爲這是可取的原因是因爲它允許您輕鬆地封裝門的開啓和關閉,並且不會公開發生該情況的條件或在繼承場景之外的功能。

public void Main() 
{ 
    var x = new InheritedAction(); 
} 

public abstract class BaseGateAction 
{ 
    public void PerformBaseAction(Action actionToPerformWhileGateIsOpen) 
    { 
     Open(); 
     actionToPerformWhileGateIsOpen(); 
     Close(); 
    } 

    private void Open() 
    { 
     Console.WriteLine("Gate has been opened"); 
    } 

    private void Close() 
    { 
     Console.WriteLine("Gate has been closed"); 
    } 
} 

public class InheritedAction : BaseGateAction 
{ 
    public InheritedAction() 
    { 
     PerformBaseAction(() => 
      Console.WriteLine("Attack the dragon while the gate is open")); 

     PerformBaseAction(() => 
     { 
      Console.WriteLine("Attack the dragon while the gate is open"); 
      Console.WriteLine("The dragon is victorious and you have been devoured"); 
     }); 
    } 
} 

此代碼示例輸出用於既PerformBaseAction方法以下分別稱之爲:

Gate has been opened 
Attack the dragon while the gate is open 
Gate has been closed 

Gate has been opened 
Attack the dragon while the gate is open 
The dragon is victorious and you have been devoured 
Gate has been closed 

這將允許不僅更好的代碼重用,但遠多個封裝的邏輯。您總是可以添加額外的暴露方法,這些方法會採用會影響您是否可以打開大門的先決條件或後置條件。

public abstract class BaseGateAction 
{ 
    ....  
    public void PerformBaseActionWithPrecondition(Func<bool> precondition, Action actionToPerformWhileGateIsOpen) 
    { 
     if (precondition()) 
     { 
      PerformBaseAction(actionToPerformWhileGateIsOpen); 
     } 
     else 
     { 
      Console.WriteLine("The gate could not be opened!"); 
     } 
    } 
    ... 
} 

這可以被稱爲如下:

PerformBaseActionWithPrecondition<bool>(
     () => true == false, 
     () => Console.WriteLine("Attack!") 
    ); 

,並會輸出:

The gate could not be opened! 
相關問題