GOF设计模式—Smalltalk MVC笔记

MVC通过建立一个“订购 /通知”协议来分离视图和模型。视图必须保证它的显示正确地反映了模型的状态。一旦模型的数据发生变化,模型将通知有关的视图,每个视图相应地得到刷新自己的机会。这种方法可以让你为一个模型提供不同的多个视图表现形式,也能够为一个模型创建新的视图而无须重写模型。

这样当然能为一个模型提供多个视图啦,因为模型不属于某一个具体的视图,这样谁都可以去使用它了。个人觉得MVC只适合用在一对多的情况下,一个模型对多个视图。不然这种分离没有啥意义,反而使模型和视图太松散了。

将对象分离,使得一个对象的改变能够影响另一些对象,而这个对象并不需要知道那些被影响的对象的细节。这个更一般的设计被描述成 Observer模式。

将对象分离就是将视图、模型、控制器分离,使模型不依赖于视图和控制器,但这样的话就会出现一个问题,当模型状态更新时,如何通知视图触发更新?如果直接通过模型通知视图,那么又会导致依赖性,为了解决这个问题,引入了Observer模式,当模型状态更新时,由观察器通知其他对象更新状态。各个视图实现Observer接口,并向模型注册。模型将跟踪由订阅更改的所有观察器组成的列表,当模型发生改变时,模型将会遍历所有已注册的观察器,并将更改通知它们,此方法通常称为"发布-订阅"。

代码1:

<input type="text" id="input">
<script>
  	// 观察器
    var observer = {
        listen:[],
        addListen(item){
            this.listen.push(item);
        },
        triggerListen(data){
            this.listen.forEach(function(item){
                item.upView(data);
            });
        }
    };
   // 模型
    var model = {
        data:"",
        upData(data){
            this.data = data;
            this.triggerListen(this.data);
        }
    };
    model.__proto__ = observer;
   // 视图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();
    model.addListen(view);
    model.addListen(view2);
</script>

模型不直接通知视图,而是通知观察器,由观察器来通知。

之前的做法可能会是下面这样:

// 模型
    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,它就只支持单继承,因此这种做法会导致它无法继承至其他对象,一个可行的解决方案是将观察器写在模型中。

<input type="text" id="input">
<script>
   // 模型
   class Model{
      constructor(){
        var data = "";
        this._listener = [];
        this.setData = function(newData){
          data = newData;
          this.triggerListen(newData);
        };
        this.getData = function(){
          return data;
        };
      }
      addListen(item){
        this._listener.push(item);
      }
      triggerListen(){
        var _this = this;
        this._listener.forEach(function(item){
            item.upView(_this.getData());
        });
      }
   }
   // 视图1
    var view = {
        upView(data){
            console.log("view1:",data);
        }
    };
   // 视图2
    var view2 = {
        upView(data){
            console.log("view2:",data);
        }
    };
    var model = new Model;
    model.addListen(view);
    model.addListen(view2);
    // 不再使用控制器
    document.getElementById("input").addEventListener("input",function(){
        model.setData(this.value);
    });
</script>

将一些对象划为一组,并将该组对象当作一个对象来使用。这个设计被描述为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 三个设计模式给出的。

模型-视图-控制器

Observer(观察器)

打赏支持我写出更多好文章,谢谢!
打赏作者
+

(^_^)打个赏喝个咖啡(^_^)

微信支付
支付宝支付
Posted on 2017-05-14 11:46  追梦子  阅读(881)  评论(0编辑  收藏  举报