zoukankan      html  css  js  c++  java
  • MVC

    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(观察器)

  • 相关阅读:
    AtCoder Beginner Contest 218 A~F 题解
    【学习笔记】光速幂
    【Nowcoder 1103A】复读数组
    【Nowcoder 1105A】集合统计
    初赛知识宝典
    KMP算法 next数组模板
    C#链接Windows远程桌面
    帝国cms 修改 上一篇 下一篇样式
    Appweb漏洞复现
    Apereo-cas漏洞复现
  • 原文地址:https://www.cnblogs.com/pssp/p/6852030.html
Copyright © 2011-2022 走看看