这是一种使用flag执行Dosomething逻辑的方法。 (C#代码和更新总是每帧调用一次。)
而且它并不是那么复杂,简单,非常简单且使用得很好。
class Monster {
bool isCalled = false;
float energy = 0.0f;
void Update()
{
energy += Random.Range(0f, 1f);
if((isCalled == false) && (energy>100.0f))
{
isCalled = true;
DoSomething();
}
}
void DoSomething(){}
}
但是,我认为布尔标志的管理是一项令人厌烦的任务。
所以我想找到更好的选择。
有没有更好或更优雅的方法来做这个(执行Dosomething一次)没有布尔标志?
例如,另一种设计模式的方式等。
答案 0 :(得分:2)
我宁愿将所有这些标志合并到一个enum
中,就像那样:
class Monster {
[Flags]
private enum Status {
Updated,
Called,
Killed,
...
}
private Status status;
void Update() {
if ((status & Status.Updated) == Status.Updated)
return;
try {
....
}
finally {
status |= Status.Updated;
}
}
}
答案 1 :(得分:1)
使用专用的名为布尔标志是明确且通用的模式。
通常您不需要专用标志,例如旧单例模式不使用bool
,而是测试特殊值:
if(instance == null)
{
.. // do something
}
如您所见,逻辑非常清晰。人们经常使用其他特殊值来避免引入标志:string.IsNullOrEmpty
,double.IsNaN
,负值等。
重要的是要有明确的意图,不要用太多小细节掩盖逻辑。如果有太多事情需要注意 - 而是引入专用旗帜。
在您的情况下,您可能希望更明显地开始使用state-machine,因为我假设Monster
可以在许多不同的状态中影响各种方法的作用:
class Monster
{
enum States { NotInitialized, Dead, Normal, EnergyMax, ... }
States _state;
float _energy;
void Update()
{
_energy += Random.Range(0f, 1f);
switch(_state)
{
case States.Normal:
if(_energy > EnergyMax)
{
DoSomething(); // called once when energy become max
_state = States.EnergyMax;
}
break;
...
}
}
...
}
答案 2 :(得分:1)
嗯,一旦执行完毕,你总是可以用NOP动作替换DoSomething
:
class Monster {
float energy = 0.0f;
Action onUpdate;
public Monster()
{
onUpdate = DoSomething;
}
void Update()
{
onUpdate();
}
void DoSomething()
{
energy += Random.Range(0f, 1f);
if(energy > 100.0f)
{
// whatever you need to do
}
onUpdate = () => {};
}
}
但是,我相信大多数开发人员都习惯使用布尔标志来跟踪这一点,如果你走这条路线,你可能会得到更少的眉毛。
答案 3 :(得分:0)
你可以这样做:
class Monster
{
private Action _doSomething;
public Monster()
{
_doSomething = DoSomething;
}
float energy = 0.0f;
void Update()
{
energy += Random.Range(0f, 1f);
if (energy > 100.0f)
if (_doSomething != null)
_doSomething();
}
void DoSomething()
{
// logic...
_doSomething = null;
}
}
但我仍然认为旗帜是一种更好的做法。必须切换一些东西。国旗/参考..
答案 4 :(得分:0)
您可以使用这样的状态模式:
class Monster
{
float energy = 0.0f;
DoSomethingState state;
public Monster()
{
this.state = new DoSomethingStateNotCalled(this);
}
public void Update()
{
energy += Random.Range(0f, 1f);
this.state.Update();
}
public void DoSomething() {
System.Diagnostics.Debug.Write("done something");
}
public float GetEnergy() {
return this.energy;
}
public void SetState(DoSomethingState state) {
this.state = state;
}
}
abstract class DoSomethingState {
protected Monster Monster;
public DoSomethingState(Monster monster) {
this.Monster = monster;
}
public abstract void Update();
}
class DoSomethingStateCalled : DoSomethingState
{
public DoSomethingStateCalled(Monster monster)
: base(monster)
{
}
public override void Update()
{
}
}
class DoSomethingStateNotCalled : DoSomethingState
{
public DoSomethingStateNotCalled(Monster monster)
: base(monster)
{
}
public override void Update()
{
if (this.Monster.GetEnergy() > 100.0f)
{
this.Monster.DoSomething();
this.Monster.SetState(new DoSomethingStateCalled(this.Monster));
}
}
}