回应老赵: 适合C# Actor的消息执行方式 -中看也中用的解决方案

  

  今天粗粗看了老赵的文章适合C# Actor的消息执行方式 -中看不(3):中用的解决方案,我在想如果用我以前写的消息总线来实现那不是中看也中用了,于是顺手写了一个测试代码(具体内容参见适合C# Actor的消息执行方式 -中看不(3):中用的解决方案回复),说来很惭愧我的消息总线系列已经一年多没有更新了,我这人太懒散惯了,没办法。废话不多说了,下面我就具体讲解一下设计思路。

  在Actor模式中,最重要的就是Actor间的消息发送以及消息路由了。

  消息发送:举一个例子实现一个ActorA向ActorB发消息,最简单的方法就是:ActorA中需要内聚或依赖一个ActorB对象,然后就可以直接发消息通讯了,这种方法优点不言而喻-简单,但是当一个系统中存在无数个Actor,一个Actor有可能向N多的其它Actor发消息,这种方法的弊端就暴露无疑了:强依赖,强耦合。 怎么结局这种问题呢,这时候设计模式中的中介者模式就可以派上用场了。所有的Actor都向中介者发消息即可,由中介者把消息通过一定的策略路由到特定的Actor,由这个特定的Actor进行处理即可。

  消息路由:消息路由的关键就是路由表,路由表可以用字典来实现,Key-可以用消息类型+Topic来标记即可,Value :就用委托函数即可。

具体简略设计图如下:

类图详解:

    ISubject<TMessage>代表Actor,该接口继承了IPublisher接口,同时定义了Observers事件,典型的观察者模式,所以该接口具有发布和订阅消息的功能。

         

 

  //发布器接口
   
public interface IPublisher
    {
        
void Publish(object sender, object msg);
    }

    
public interface IPublisher<TMessage> : IPublisher
    {
        
void Publish(object sender, TMessage msg);
    }

    //Actor 接口
    
public interface ISubject:IPublisher
    {

        //发布消息的Topic名称
        
string Name { getset; }
        
void Close();//退出,从消息总线中移除该Topic的Actor
    }

    
public interface ISubject<TMessage> : ISubject,IPublisher<TMessage>
    {

       //观察者集合
        
event ObserverHandler<TMessage> Observers;

        //消息订阅者
        ISubscriber
<TMessage> Subscriber { getset; }
        

        //消息队列
        IQueue
<KeyValuePair<object,TMessage>> Queue { getset; }

       //消息执行器
        IExecutor
<TMessage> Executor { getset; }

        
bool Closed { get; }
    }

 

            IMessageRouter 内聚了ISubject(Actor)的字典,Actor的消息发送以及消息接收的重担全部都交给了IMessageRouter,使Actor和Actor之间不需要知道对方的存在,Actor只需要发布消息(或基于Topic的消息)即可,或者只需要接受消息(或基于Topic的消息)即可。

 

        //Delete Subject by Message Type or Topic
        
void Remove<TMessage>();
        
void Remove<TMessage>(string topic);
        
void Remove(Type type);
        
void Remove(string topic, Type type);

       //订阅消息-注册观察者
        
void Subscribe<TMessage>(ObserverHandler<TMessage> handler);
        
void Subscribe<TMessage>(string topic, ObserverHandler<TMessage> handler);
        
void Subscribe<TMessage>(object observer, ObserverHandler<TMessage> handler);
        
void Subscribe<TMessage>(string topic,object observer, ObserverHandler<TMessage> handler);
        //移除订阅者
        
void Unsubscribe<TMessage>(ObserverHandler<TMessage> handler);
        
void Unsubscribe<TMessage>(string topic, ObserverHandler<TMessage> handler);
        
       //订阅前置过滤器消息 - 注册前置过滤器观察者
        
void SubscribePreFilter<TMessage>(PreFilterHandler<TMessage> handler);
        
void SubscribePreFilter<TMessage>(string topic, PreFilterHandler<TMessage> handler);
        
void SubscribePreFilter<TMessage>(object sender, PreFilterHandler<TMessage> handler);
        
void SubscribePreFilter<TMessage>(string topic, object sender, PreFilterHandler<TMessage> handler);

        
void UnsubscribePreFilter<TMessage>(PreFilterHandler<TMessage> handler);
        
void UnsubscribePreFilter<TMessage>(string topic,PreFilterHandler<TMessage> handler);
        
       //注册过滤器消息 - 注册过滤器观察者
        
void SubscribeFilter<TMessage>(FilterHandler<TMessage> handler);
        
void SubscribeFilter<TMessage>(string topic, FilterHandler<TMessage> handler);
        
void SubscribeFilter<TMessage>(object observer, FilterHandler<TMessage> handler);
        
void SubscribeFilter<TMessage>(string topic, object observer, FilterHandler<TMessage> handler);

        
void UnsubscribeFilter<TMessage>(FilterHandler<TMessage> handler);
        
void UnsubscribeFilter<TMessage>(string topic, FilterHandler<TMessage> handler);


        
int Count { get; }
       

        //注册钩子(钩子的部分函数也可充当消息过滤器使用)
        
void RegisterHook(params IHook[] hooks);
        
void UnRegisterHook(params IHook[] hooks);

       //发布消息
        
void Publish<TMessage>(TMessage msg);

        void Publish<TMessage>(string topic, TMessage msg);//发布基于主题的消息
        
void Publish<TMessage>(object sender, TMessage msg);
        
void Publish<TMessage>(string topic, object sender, TMessage msg);//发布基于主题的消息


       //推荐方式:注册卸载发布基于主题的消息
        
void SubscribeTopic<TMessage>(string topic, ObserverHandler<Topic<TMessage>> handler);
        
void UnsubscribeTopic<TMessage>(string topic, ObserverHandler<Topic<TMessage>> handler);
        
void PublishTopic<TMessage>(Topic<TMessage> topic);

        
void Clear();
    }

 

     改进版的Ping/Pong, Ping和Pong互不依赖,它们之间仅仅通过Topic和消息类型作为标签进行通讯

Topics 定义:

 

 

消息类:就用Int类型

Ping 类的实现代码:

 

 

 

Pong 类的实现非常简单:

 

 

测试代码:

 

 

程序输出:

Ping sent  :5
Pong received ping :5
Pong sent  :5
Ping received pong :5


Ping sent  :4
Pong received ping :4
Pong sent  :4
Ping received pong :4


Ping sent  :3
Pong received ping :3
Pong sent  :3
Ping received pong :3


Ping sent  :2
Pong received ping :2
Pong sent  :2
Ping received pong :2


Ping sent  :1
Pong received ping :1
Pong sent  :1
Ping received pong :1
Finished

OK,暂时先写到这里,欢迎大家一起进行交流!

posted @ 2009-07-17 14:53  风云  阅读(2703)  评论(25编辑  收藏  举报