1

我有一个模型程序,表示沿服务器链的消息流:

public class MyModel
{
    static bool x_send_msg1 = false; // has X sent msg1?
    static bool y_recv_msg1 = false; // has Y received msg1?

    static bool y_send_msg1 = false; // has Y sent msg1?
    static bool z_send_msg1 = false; // has Z received msg1?

    // (etc for more servers and more messages)

    [Action]
    static void YSendMsg1()
    {
       // Y sends Msg1 to Z
       y_send_msg1 = true;
       z_recv_msg1 = true;
    }
    static bool YSendMsg1Enabled()
    {
       // in the simplest case, this can happen whenever Y has received the
       // message but not yet forwarded it
       return y_recv_msg1 && !y_send_msg1;
    }

}

还有很多消息。每个服务器和消息类型的 Enabled() 逻辑略有不同,但状态相似,所以我想通过编写类似的东西来封装它:

class State
{
    public bool send_msg1 = false;
    public bool recv_msg1 = false;
}
public static State X = new State();
public static State Y = new State();

然后在我的操作中使用封装状态:

[Action]
static void YSendMsg1()
{
  // instead of y_qqq above, now we can write Y.qqq:
   Y.send_msg1 = true;
   Z.recv_msg1 = true;
}
static bool YSendMsg1Enabled()
{
   return Y.recv_msg1 && !Y.send_msg1;
}

但是 NModel 不会让我以这种方式使用对象来保持我的状态。有没有其他方法可以避免定义重复的布尔值组,一个用于链中的每个服务器?

4

3 回答 3

2

撇开风格问题不谈,如问题所示封装状态的主要好处是减少了必须编写和阅读的代码量。不必编写 (#servers * #messages) 声明,只需要 (#server + #messages)。

通过使用 NModel 的内置Set类来跟踪每条消息的状态,可以实现同样的代码减少(可读性的相应改进和腕管综合症的减少)。一个名为的集合send_msg1包含所有已发送的服务器的名称msg1

public class MyModel
{
    static set<int> send_msg1 = set<int>.EmptySet; // has server #n sent msg #1?
    static set<int> recv_msg1 = set<int>.EmptySet; // has server #n received msg #1?
    // (etc for more messages)

    static int X = 1;
    static int Y = 2;
    // (etc for more server names)

    [Action]
    static void YSendMsg1()
    {
       // Y sends Msg1 to Z
       send_msg1 = send_msg1.Add(Y);
       recv_msg1 = recv_msg1.Add(Z);
    }
    static bool YSendMsg1Enabled()
    {
       // in the simplest case, this can happen whenever Y has received the
       // message but not yet forwarded it
       return recv_msg1.Contains(Y) && !send_msg1.Contains(Y);
    }

}

(可以进一步减少代码事件的数量,例如,通过使用集合映射将所有内容保存在单个变量中。但是,将状态部分分开的一个优点是它可以在模型查看器中生成更清晰的状态摘要.)

于 2009-12-18T19:38:33.250 回答
1

自从在上面写下我的答案后,我了解到另一种更接近我最初寻找的解决方案。

要将对象与实例变量一起使用,您可以从LabeledInstance如下所示派生。应该使用静态Create()方法分配实例,并且应该在重写的Initialize()方法中初始化字段。

(您也可以对操作使用实例方法,但要这样做,您必须为该类分配一个域;该域的名称应对应于包含该类的所有当前实例的静态集。)

在幕后,NModel 将把这个类翻译成一堆映射,一个对应于类中的每个实例变量。这些映射的键将是类名的索引实例,例如State(1). 这在 MVC 工具中可能有点难以阅读,因此您可能还希望保留某种实例变量,其中包含对象状态的清晰、综合摘要。

class State : LabeledInstance<State>
{ 
    public override void Initialize()
    {
        send_msg1 = false;
        recv_msg1 = false;
    }
    public bool send_msg1;
    public bool recv_msg1;
} 

public static State X = State.Create();
public static State Y = State.Create();
于 2010-01-14T20:20:48.997 回答
0

我认为观察者模式可能会对您有所帮助 - http://www.dofactory.com/Patterns/PatternObserver.aspx

于 2009-12-17T12:55:07.370 回答