2015-02-10 157 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! 
相关问题