观察者模式之授人与柄
拟人化一点的说法就是两个人互相拿着一根连着对方的线,这跟线就是对方的引用,引用就是句柄,所以叫授人与柄.
用不拟人的说法就是两个对象想互相操作, 就互相持有对方的柄(引用或者指针,类似于链表),双方进行通信的基础就是共同知道的一套规范(接口)
个人理解的设计模式就是将需要达到的功能,用恰当的数据结构来表示出来,同时加上一些约定,让双方或多方协同工作。
就是将数学的映射用代码表达出来。比如SQL=集合运算,SQL写不好的可以看看高等数学第一章,换个数学的角度看编程,也许世界就不一样了呢。
java定义一个接口为了让双方对disaplay有共同的理解,调用方说 你给我显示一下与被调用放的显示一下拥有同样的语义。
public interface DisaplayElement { void disaplay(); }
public class source{ private List<DisaplayElement> list; private String msg; public void reg(DisaplayElement disaplay){ this.list.add(disaplay); } public void notice(String msg){ for(DisaplayElement disaplay:list){ disaplay.disaplay(msg); } } }
然后下面是JS写的一个小DEMO,在木有接口类型的世界里简直是随心所欲
var source ={//数据源对象 regList:[],//存放柄对象的数据结构 /** 注册列表数据结构如果是数组,只能做到全体通知执行。 如果是键值对结构 { {type1:[组件1,组件2...]}, {type2:[组件n1,组件n2...]} },可以分类型进行通知,观察者模式的灵活性在于注册列表的数据结构,根据自身业务建立不同的数据模型。 **/ msg:'',//双方进行传递的消息对象,根据业务构建,Demo中定义为字符串演示 isChange:false,//消息改变标记,消息改变时作为接收方进行拉取数据的标记 reg:function(obj){ regList.add(obj); }, setMsg:function(msg){//设置改变 同时通知观察者 isChange=true;//设置状态改变 for(var i in regList){ regList[i].callBack(this,msg); } isChange=false;//执行完毕清除状态标记 }, getMsg:function(){//提供拉取消息操作 return this.msg; } } var disaplay ={//显示器 可以改成prototype的方式 把通用方法写到原型上 然后把各实例对象重写show方法。 source:null, show:function(msg){//这里写获取通知的后业务逻辑,可以抽离到各自的新观察者对象上,原型上保存空实现或者默认实现 alert(msg); }, callBack:function(obj,msg){//约定的回调接口,观察者对象的引用 可以在此处主动获取数据 show(msg);//推的方式 }, getChange:function(){ if(source.change){ var msg = source.getMsg(); alert('拉过来的消息'+msg); } }, Make:function(source){//构造函数 将源对象的柄拿过来 var obj = new watcher(); obj.source = source; source.reg(this) return obj; } } //以上类已经构造完毕 //下面写注册调用 var disaplay1 = watcher.Make(source); disaplay1.show=function(msg){ alert("开心的告诉你们哇"+msg); } var disaplay2 = watcher.Make(source); disaplay2.show=function(msg){ alert("生气的告诉你们哇"+msg); } source.setMsg('通知你们去食堂吃饭');