文章出處

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


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()