强类型消息
为了避免繁琐的转型,为了获得类型安全的各种优势,我们也可以选择为每种不同的消息创建独立的类型。不过由于一个Actor往往会应对各种消息,因此在.NET环境中,往往我们需要把消息类型定义为object。如果使用ActorLite来演示的话,代码可能是这样的:
class Person : Actor<object>
{
protected override void Receive(object message)
{
if (message is ChatMessage)
{
ChatMessage chatMsg = (ChatMessage)message;
Person another = chatMsg.Another;
Topic topic = chatMsg.Topic;
// ...
}
else if (message is EatMessage)
{
EatMessage eatMsg = (EatMessage)message;
Restaurant restaurant = eatMsg.Restaurant;
// ...
}
else if (message is WorkMessage)
{
WorkMessage workMsg = (WorkMessage)message;
Person reportTo = workMsg.ReportTo;
Job job = workMsg.Job;
// ...
}
}
}
{
protected override void Receive(object message)
{
if (message is ChatMessage)
{
ChatMessage chatMsg = (ChatMessage)message;
Person another = chatMsg.Another;
Topic topic = chatMsg.Topic;
// ...
}
else if (message is EatMessage)
{
EatMessage eatMsg = (EatMessage)message;
Restaurant restaurant = eatMsg.Restaurant;
// ...
}
else if (message is WorkMessage)
{
WorkMessage workMsg = (WorkMessage)message;
Person reportTo = workMsg.ReportTo;
Job job = workMsg.Job;
// ...
}
}
}
图示如下:
使用if…else来进行逻辑分支判断还是必要的,不过我们这里使用了静态类型代替了Magic String(当然在使用Tag Message时也可以使用常量)的判断,同时危险而麻烦的类型转换操作也减少的。与Tag Message相比,这种做法获得了一定的类型安全优势,可以得到编译器的静态检查,做起重构来也有了依据。不过他也有比较明显的缺陷,那就是需要构建大量的消息类型。要知道消息类型的数量很可能是Actor类型数量的几倍,每种消息类型还包含着多个属性,构造函数接受参数,然后在构造函数里设置属性……这种做法对复杂性的提升还是较为可观的,有时候会感觉还不如使用简单的Tag Message。