统一对象消息编程详解——包装其他类

     消息编程改变了传统编程的规则,以往我们通过对象的实例句柄来操纵对象,现在我们的对象有了名字,我们通过对象的名字去与对象互动,以往我们直接执行对象的方法,现在我们通过给对象传递消息由对象自己执行。

   我们已有许多完善、实用、现成的各种工具类,我们不可能用消息编程的理念而重新开发这些工具,因此用消息对象包装现有的各种工具类是非常必要,而且必须的。

  将传统的类改造为消息对象非常容易,用简单的对象组合模式。

  现在我们假设一个传统对象 classA ,它有两个公开方法 m1(string param1,string param2),m2()。以往我们使用对象的方式如下:

  classA aobj =new classA();
   aobj.m1("p1","p2");
   aobj.m2();

用消息对象包装后这样的:

public class newcalssA extends TLBaseModule {
    private classA aobj ;
    public newcalssA(){
        super();
    }
    public newcalssA(String name ){
        super(name);
    }
    public newcalssA(String name , TLObjectFactory modulefactory)
    {
        super(name,modulefactory);
    }
    @Override
    protected void init() {
        aobj =new classA();
    }

    @Override
    protected TLMsg checkMsgAction(Object fromWho, TLMsg msg) {
        TLMsg returnMsg=null;
        switch (msg.getAction()) {
            case "m1":
                m1(fromWho,msg);
                break;
            case "m2":
                m2(fromWho,msg);
                break;

            default:

        }
        return returnMsg ;
    }
    private void m1(Object fromWho, TLMsg msg) {
        String param1= (String) msg.getParam("param1");
        String param2= (String) msg.getParam("param1");
        aobj.m1(param1,param2);
    }
    private void m2(Object fromWho, TLMsg msg) {
        aobj.m2();
    }

}

原对象成为新对象的内部属性,原对象的方法变为内部方法,只能由该对象内部执行。这时我们这样使用对象:

1、首先将对象加入工厂配置中,对象的创建由工厂负责。我们给对象起一个名字 mynewClass,以后通过这个名字来访问对象。

<module name="mynewClass" classfile="newcalssA" />

2、使用时我们先建立消息指令

TLMsg amsg =new TLMsg();
amsg.setAction("m1").setParam("param1","p1").setParam("param2","p2");
或 :
TLMsg amsg =createMsg().setAction("m1").setParam("param1","p1").setParam("param2","p2");

3、将消息发送给对象

  putMsg("mynewClass",amsg);

消息对象接收消息后,自动解析消息中的action而执行相应的方法。

这样将一个传统的对象包装成消息对象,而具有消息对象的一切特征了。

以往我们直接执行对象的方法,现在通过消息来间接执行,似乎多次一举,降低效率。其实不然,由于有了消息对象的特征,我们可以灵活的控制、运行。举例如下:

1、以往我们要将对象实例化后才能调用,现在可以通过名字“mynewClass” 来标称对象。任何地方都不需实例化了,用名字就可。例如对象B(前提B也是消息对象)也使用它,那么对象B直接putmsg(“mynewClass”,msg)即可。名字是方便传递、存储的,而对象内存句柄很难。配置文件中也很简单,直接写对象名字。

2、应用更加灵活

  例1:

上面以往我们代码中直接执行方法aobj.m1("p1","p2");过段时间如果想在执行该方法前调用对象C的一个方法action1,根据C的结果来判断是否继续执行,或者通过C的方法来过滤参数p1,那么我们必须来改代码。现在,我们可以通过多种方式灵活的实现:

  ——在mynewClass的配置文件中增加消息前期处理

 <beforeMsgTable>
        <action  value="m1" >
            <msg  action="action1"  destination="cobj"  useInputMsg="false" usePreReturnMsg ="false" />
        </action>
    </beforeMsgTable>

那么,在执行m1方法前自动执行cobj的action1,我们无需改代码。 <beforeMsgTable>项中可以加许多执行消息项。同样我们也可以增加消息后期处理,m1方法执行完后继续执行其他的方法。

—— 通过消息链

        我们先形成个消息l来执行C的方法 ——cactionmsg,然后将执行m1的消息附加在后面 cationmsg.setNextmsg(amsg),然后传送给对象, putMsg("mynewClass",cactionmsg),这样对象先后执行两个消息。

——我们不对外公布方法m1,在配置中配置消息路由链表

<!-- 消息路由表-->
<msgTable>
    <msgid  value="m1msg" >
        <msg action="action1" destination="cojb" />
        <msg action="m1"  />
    </msgid>
</msgTable>

   上面配置中,消息链表表明消息id为"m1msg"的消息包含两个消息。其他对象发送设置了消息id(方法 msg.setMsgId("m1msg") )的消息给对象,对象自动根据消息id匹配相关的消息链而依次执行。

例2:

以往对象的实例化后,它的初始化行为是固定,例如实例化后它执行 myinit(),我们没法改变。现在我们可以在配置文件中增加初始化消息表

    <initMsg>
            <msg action="m2"   ></msg>
            <msg action="getuser"  destination="user"  ></msg>
    </initMsg>

这样对象模块初始化后,自动执行自己的m2方法,然后执行对象user的getuser方法。运行更加的灵活。

例3:

  对象自动继承了父类消息对象模板的一些系统功能,例如动态重载配置,重新加载模块等功能

例4:

以往如果我们想异步执行对象的方法比较麻烦,例如想异步执行上面对象的m1方法,首先我们要建立了线程类对象,然后在线程类中实例化A对象,执行A的方法。如果方法结果返回,则要传入回调函数或对象。可以说代码一大堆。现在我们非常简单的完成,因为我们的消息类TLMsg自带异步标志,只要我们对上面的消息设置下异步标志即可 amsg..setWaitFlag(false),同样的发送给对象  putMsg("mynewClass",amsg) ,则对象自动启动一个线程执行m1方法。在发送给对方消息时,我们已经自动将自己的对象实例句柄带人方法中,m1(Object fromWho, TLMsg msg) ,fromWho为调用对象实例句柄,因此可以方便返回结果。任何消息,无论是初始化消息表还是上面加的前后执行的消息,只要设置了异步标志,就自动异步执行。

例5

 包装了消息对象后,由于只有两个public方法,既putmsg和getmsg,那么对象更加的独立,减少了依赖、方便了对象之间的解耦。对象的方法都是内部执行,对于对象的内部改变不影响其他对象。

例6

  以往任何人都可以实例化对象而执行它的方法,例如上面只要我们实例化对象A后就可以执行aobj.m1("p1","p2")。也就是被执行者无法选择执行者。现在我们重新包装后的方法 m1(fromWho,msg),传入了执行者fromWho,那么我们就可以对执行者检测,看其是否有执行条件,同时,在消息TLMsg中也有创建者的信息。

例7

  我觉得这是很重要的一点,现在我们包装的消息对象不仅可以执行自己的原有方法,还可以传递消息,起到消息路由功能。这特别适合一些消息接口或者消息网关,如我web框架里的urlmap映射模块或者Web服务接口模块。下面是我服务端对app客户端一个接口配置:

<msgTable>
        <!-- client的msgid 对应的服务msg-->
        <msgid value="postInfo" >
            <msg  destination="infomationControl"  action="postInfo" />
        </msgid>
        <msgid value="usersinfo" >
            <msg  destination="infomationControl"  action="queryByUserid"/>
        </msgid>
        <msgid value="queryInfoById" >
            <msg  destination="infomationControl"  action="queryInformationById"/>
        </msgid>
        <msgid value="getReply" >
            <msg  destination="infomationControl"  action="getReply" />
        </msgid>
        <msgid value="postReply" >   
    </msgTable>

app客户端传递来的json数据中包含消息id,服务端接口自动根据消息id传递给相应的执行模块。

总之 ,将对象消息包装化后,不是简单的调用方法的改变,更丰富了它的功能,也更加的灵活。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值