
从这个图我们可以看出
1.消费者和出版社互相不认识,消费者不需要了解他想要的杂志是具体哪家出版社出的;出版社也不需要了解具体是哪个人定了他们出版社发行的书。
2.消费者和出版社必须都认识邮局。
3.消费者需要告诉邮局消费者的名字地址以及想要订阅的杂志名字
4.可以多个消费者订阅同一本杂志
5.邮局拿到杂志后,会一一通知消费者,通知的时候同时把杂志送到消费者手里。
看完上面现实例子,我们再来看抽象的描述会更清晰一点,看下图:

和上面的实际例子描述一一对应:
1.系统/开发者和函数对象互相不依赖,系统/开发者只管触发一个消息,并不关心谁去接受
2.系统/开发者和函数对象必须能获取到消息源对象
3.函数对象订阅消息的时候需要标示消息的名称和函数对象的引用
4.可以多个函数对象订阅同一个消息源同一名字的消息
5.消息源触发消息会一一通知所有订阅者,并把data数据传递到回调函数对象
看完抽象的描述,我们最后来看实际的deviceone开发的例子,还是以do_Button为例子。
1. 当用户点击一个button,触摸到的时候,系统会获取到button这个对象作为消息源,fire一个”touch”消息,任何订阅了”touch”消息的函数对象都会接收到这个消息并引起函数的执行。
//获取button对象var btn_hello = ui("btn_hello");//定义函数对象function f(){//当btn_hello这个按钮接收到手指点击就会执行下面的代码deviceone.print("f 函数接收到点击触发消息")}function f(){//当btn_hello这个按钮接收到手指点击就会执行下面的代码deviceone.print("f 函数接收到点击触发消息")}//f,f订阅button的touch消息btn_hello.on("touch",f);btn_hello.on("touch",f);2. 我们可以为button对象定义2个自定义的消息”message1”和”message2”,分别有2个函数对象订阅这2个消息。但是最后要触发这个消息必须是开发者通过调用fire函数才能触发,这就是和系统消息的区别。//获取button对象var btn_hello = ui("btn_hello");//定义函数对象function f(d){//当btn_hello这个按钮接收到开发者触发的消息message就会执行下面的代码deviceone.print("f 函数接收到message消息,消息的数据是:"+d)}function f(d){//当btn_hello这个按钮接收到开发者触发的消息message就会执行下面的代码deviceone.print("f 函数接收到message消息,消息的数据是:"+d)}//f,f订阅button的touch消息btn_hello.on("message",f);btn_hello.on("message",f);//触发消息btn_hello.fire("message","data");btn_hello.fire("message","data");看到这里,你肯定会奇怪,为什么我们要在button上自定义对象?这有神马意义?其实确实没有意义也没有必要,这里只是拿button举例子,在常规的开发中,基本不会这么用。// SM对象可以是消息源var page = sm("do_Page");page.on("loaded",function()){// 这个是page对象的系统消息,这个消息不需要手动触发,系统会自动触发}page.on("message",function(d)){// 这个是page对象的自定义消息}page.fire("message","data");// MM对象可以是消息源var http = mm("do_Http");http.on("result",function()){// 这个是http对象的系统消息,这个消息不需要手动触发,接受到http服务端的反馈后会自动触发}http.on("message",function(d)){// 这个是http对象的自定义消息}http.fire("message","data");//UI对象可以是消息源var alayout = ui("alayout_id");alayout.on("touch",function()){// 这个是alayout对象的系统消息,这个消息不需要手动触发,手机点击就会触发}alayout.on("message",function(d)){// 这个是alayout对象的自定义消息}alayout.fire("message","data");2.消息源对象有作用域,所以订阅和触发的消息源必须是是一个作用域的同一个对象。这里结合数据分享和数据传递文档来理解。//在test.ui.js里订阅消息var page = sm("do_Page");deviceone.print(page.getAddress());page.on("message",function(d)){deviceone.print(d);}//在test.ui.js触发消息var page = sm("do_Page");deviceone.print(page.getAddress());page.fire("message","data");如果不在同一page作用域,则可以把消息订阅在2个page都能共享到的app作用域//在test.ui.js里订阅消息var app = sm("do_App");app.on("message",function(d)){deviceone.print(d);}//在test.ui.js触发消息var app = sm("do_App");app.fire("message","data");3.同样的函数对象可以重复订阅一个对象源的消息,触发消息的时候会使函数执行多次,这是初学者经常犯的错误。var page = sm("do_Page");var count = ;function f(){deviceone.print("执行次数"+(count++));}page.on("message",f);page.on("message",f);page.fire("message");看上面的例子,如果执行的话,会打印2此,因为订阅了2次,或许你会说谁会写这样的代码?实际情况肯定没有这么容易看出来执行了重复的on函数,实际情况经常是比如在点击事件里执行on函数,每点击一下按钮,就重复订阅一次。var page = sm("do_Page");var count = ;function f(){deviceone.print("执行次数"+(count++));}page.fire("message");page.on("message",f);看上面的例子,如果执行的话,会没有效果,或许你会说谁会写这样的代码?实际情况肯定没有这么容易看出来顺序反了,实际情况经常是比如on函数执行在某一个函数的回调函数里,你无法确定回调函数啥时候执行,是否是在fire之前执行。一般碰到这种情况可以加几个deviceone.print打印一下看看是on先执行还是fire先执行。var page = sm("do_Page");var count = ;function f(){deviceone.print("执行次数"+(count++));}page.on("message",f);page.fire("message");.page.off("message");page.fire("message");