GOF设计模式—Smalltalk MVC笔记
MVC通过建立一个“订购 /通知”协议来分离视图和模型。视图必须保证它的显示正确地反映了模型的状态。一旦模型的数据发生变化,模型将通知有关的视图,每个视图相应地得到刷新自己的机会。这种方法可以让你为一个模型提供不同的多个视图表现形式,也能够为一个模型创建新的视图而无须重写模型。
这样当然能为一个模型提供多个视图啦,因为模型不属于某一个具体的视图,这样谁都可以去使用它了。个人觉得MVC只适合用在一对多的情况下,一个模型对多个视图。不然这种分离没有啥意义,反而使模型和视图太松散了。
将对象分离,使得一个对象的改变能够影响另一些对象,而这个对象并不需要知道那些被影响的对象的细节。这个更一般的设计被描述成 Observer模式。
将对象分离就是将视图、模型、控制器分离,使模型不依赖于视图和控制器,但这样的话就会出现一个问题,当模型状态更新时,如何通知视图触发更新?如果直接通过模型通知视图,那么又会导致依赖性,为了解决这个问题,引入了Observer模式,当模型状态更新时,由观察器通知其他对象更新状态。各个视图实现Observer接口,并向模型注册。模型将跟踪由订阅更改的所有观察器组成的列表,当模型发生改变时,模型将会遍历所有已注册的观察器,并将更改通知它们,此方法通常称为"发布-订阅"。
代码1:
模型不直接通知视图,而是通知观察器,由观察器来通知。
之前的做法可能会是下面这样:
// 模型 var model = { data:"", upData(data){ this.data = data; view.upView(this.data); view.upView2(this.data); } }; // 视图1 var view = { upView(data){ console.log("view1:",data); } }; // 视图2 var view2 = { upView(data){ console.log("view2:",data); } }; // 控制器 var controller = { event(){ document.getElementById("input").addEventListener("input",function(){ model.upData(this.value); }); } }; controller.event();
由于模型和视图直接接触,导致一旦再添加视图或删除,都需要去操作模型内部代码,如果代码是自己写还好,如果交由同事,这种写法就不是很好了。以上代码还算好的了,如果将模型和数据混在一起,当新增一个模型时又得重新写一份模型了。
在这几段代码中,我发现控制器的概念就不是那么强烈了,可有可无,因为控制器的作用就是解释用户的鼠标和键盘输入,以通知模型或视图进行相应的更改,而在web浏览器中,我们只需要通知模型,而通知模型web浏览器提供了事件机制。
在代码1中,由于模型继承至观察器,而某些语言如javascript,它就只支持单继承,因此这种做法会导致它无法继承至其他对象,一个可行的解决方案是将观察器写在模型中。
将一些对象划为一组,并将该组对象当作一个对象来使用。这个设计被描述为C o m p o s i t e 模式,该模式允许你创建一个类层次结构,一些子类定义了原子对象(如B u t t o n)而其他类定义了组合对象( C o m p o s i t e Vi e w ),这些组合对象是由原子对象组合而成的更复杂的对象
从细颗粒到一粒再由粒组合粒成为一个组,由组再组合形成一个对象,如果要使用原子对象,那么得考虑清楚是否有必要,毕竟原子对象太过于原始,要说组合,function就是最好的例子。
一个策略是一个表述算法的对象。当你想静态或动态地替换一个算法,或你有很多不同的算法,或算法中包含你想封装的复杂数据结构,这时策略模式是非常有用的。
每个算法都是独立的,使用的时候传递相应的算法。
M V C 的主要关系还是由 O b s e r v e r 、C o m p o s i t e 和S t r a t e g y 三个设计模式给出的。