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

  • 相关阅读:
    什么样的代码称得上是好代码?
    九年程序人生 总结分享
    Docker入门 第一课 --.Net Core 使用Docker全程记录
    阿里云 Windows Server 2012 r2 部署asp.net mvc网站 平坑之旅
    Visual studio 2015 Community 安装过程中遇到问题的终极解决
    Activiti6.0 spring5 工作流引擎 java SSM流程审批 项目框架
    java 进销存 库存管理 销售报表 商户管理 springmvc SSM crm 项目
    Leetcode名企之路
    24. 两两交换链表中的节点
    21. 合并两个有序链表
  • 原文地址:https://www.cnblogs.com/pssp/p/6852030.html
Copyright © 2011-2022 走看看