在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ Mixin 模式
中介者模式
MVVM
亨元模式
設計模式分類概覽表
ES Harmony
組合模式
CommonJS
jQuery 插件的設計模式
外觀模式
觀察者模式
建造者模式
構造器模式
外觀模式
簡介
AMD
原型模式
設計模式的分類
觀察者模式
命名空間模式
代理模式
編寫設計模式
適配器模式
反模式
什么是設計模式
模塊化模式
MVC
Mixin 模式
裝飾模式
設計模式的結構
單例模式
迭代器模式
命令模式
工廠模式
MVP
暴露模塊模式
惰性初始模式

Mixin 模式

在諸如C++或者List著這樣的傳統(tǒng)語言中,織入模式就是一些提供能夠被一個或者一組子類簡單繼承功能的類,意在重用其功能。

子類劃分

對于不熟悉子類劃分的開發(fā)者,在深入織入模式和裝飾器模式之前,我們將對他們進行一個簡短的初學者入門指引。

子類劃分是一個參考了為一個新對象繼承來自一個基類或者超類對象的屬性的術語.在傳統(tǒng)的面向對象編程中,類B能夠從另外一個類A處擴展.這里我們將A看做是超類,而將B看做是A的子類.如此,所有B的實體都從A處繼承了其A的方法.然而B仍然能夠定義它自己的方法,包括那些重載的原本在A中的定義的方法。

B是否應該調用已經被重載的A中的方法,我們將這個引述為方法鏈.B是否應該調用A(超類)的構造器,我們將這稱為構造器鏈。

為了演示子類劃分,首先我們需要一個能夠創(chuàng)建自身新實體的基對象。

var Person =  function( firstName , lastName ){

  this.firstName = firstName;
  this.lastName =  lastName;
  this.gender = "male";

};

接下來,我們將制定一個新的類(對象),它是一個現有的Person對象的子類.讓我們想象我們想要加入一個不同屬性用來分辨一個Person和一個繼承了Person"超類"屬性的Superhero.由于超級英雄分享了一般人類許多共有的特征(例如:name,gender),因此這應該很有希望充分展示出子類劃分是如何工作的。

// a new instance of Person can then easily be created as follows:
var clark = new Person( "Clark" , "Kent" );

// Define a subclass constructor for for "Superhero":
var Superhero = function( firstName, lastName , powers ){

    // Invoke the superclass constructor on the new object
    // then use .call() to invoke the constructor as a method of
    // the object to be initialized.

    Person.call( this, firstName, lastName );

    // Finally, store their powers, a new array of traits not found in a normal "Person"
    this.powers = powers;
};

SuperHero.prototype = Object.create( Person.prototype );
var superman = new Superhero( "Clark" ,"Kent" , ["flight","heat-vision"] );
console.log( superman );

// Outputs Person attributes as well as powers

Superhero構造器創(chuàng)建了一個自Peroson下降的對象。這種類型的對象擁有鏈中位于它之上的對象的屬性,而且如果我們在Person對象中設置了默認的值,Superhero能夠使用特定于它的對象的值覆蓋任何繼承的值。

Mixin(織入目標類)

在Javascript中,我們會將從Mixin繼承看作是通過擴展收集功能的一種途徑.我們定義的每一個新的對象都有一個原型,從其中它可以繼承更多的屬性.原型可以從其他對象繼承而來,但是更重要的是,能夠為任意數量的對象定義屬性.我們可以利用這一事實來促進功能重用。

Mix允許對象以最小量的復雜性從它們那里借用(或者說繼承)功能.作為一種利用Javascript對象原型工作得很好的模式,它為我們提供了從不止一個Mix處分享功能的相當靈活,但比多繼承有效得多得多的方式。

它們可以被看做是其屬性和方法可以很容易的在其它大量對象原型共享的對象.想象一下我們定義了一個在一個標準對象字面量中含有實用功能的Mixin,如下所示:

var myMixins = {

  moveUp: function(){
    console.log( "move up" );
  },

  moveDown: function(){
    console.log( "move down" );
  },

  stop: function(){
    console.log( "stop! in the name of love!" );
  }

};

然后我們可以方便的擴展現有構造器功能的原型,使其包含這種使用一個 如下面的score.js_.extends()方法輔助器的行為:

// A skeleton carAnimator constructor
function carAnimator(){
  this.moveLeft = function(){
    console.log( "move left" );
  };
}

// A skeleton personAnimator constructor
function personAnimator(){
  this.moveRandomly = function(){ /*..*/ };
}

// Extend both constructors with our Mixin
_.extend( carAnimator.prototype, myMixins );
_.extend( personAnimator.prototype, myMixins );

// Create a new instance of carAnimator
var myAnimator = new carAnimator();
myAnimator.moveLeft();
myAnimator.moveDown();
myAnimator.stop();

// Outputs:
// move left
// move down
// stop! in the name of love!

如我們所見,這允許我們將通用的行為輕易的"混"入相當普通對象構造器中。

在接下來的示例中,我們有兩個構造器:一個Car和一個Mixin.我們將要做的是靜Car參數化(另外一種說法是擴展),以便它能夠繼承Mixin中的特定方法,名叫driveForwar()和driveBackward().這一次我們不會使用Underscore.js。

取而代之,這個示例將演示如何將一個構造器參數化,以便在無需重復每一個構造器函數過程的前提下包含其功能。

// Define a simple Car constructor
var Car = function ( settings ) {

        this.model = settings.model || "no model provided";
        this.color = settings.color || "no colour provided";

    };

// Mixin
var Mixin = function () {};

Mixin.prototype = {

    driveForward: function () {
        console.log( "drive forward" );
    },

    driveBackward: function () {
        console.log( "drive backward" );
    },

    driveSideways: function () {
        console.log( "drive sideways" );
    }

};

// Extend an existing object with a method from another
function augment( receivingClass, givingClass ) {

    // only provide certain methods
    if ( arguments[2] ) {
        for ( var i = 2, len = arguments.length; i < len; i++ ) {
            receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]];
        }
    }
    // provide all methods
    else {
        for ( var methodName in givingClass.prototype ) {

            // check to make sure the receiving class doesn't
            // have a method of the same name as the one currently
            // being processed
            if ( !Object.hasOwnProperty(receivingClass.prototype, methodName) ) {
                receivingClass.prototype[methodName] = givingClass.prototype[methodName];
            }

            // Alternatively:
            // if ( !receivingClass.prototype[methodName] ) {
            //  receivingClass.prototype[methodName] = givingClass.prototype[methodName];
            // }
        }
    }
}

// Augment the Car constructor to include "driveForward" and "driveBackward"
augment( Car, Mixin, "driveForward", "driveBackward" );

// Create a new Car
var myCar = new Car({
    model: "Ford Escort",
    color: "blue"
});

// Test to make sure we now have access to the methods
myCar.driveForward();
myCar.driveBackward();

// Outputs:
// drive forward
// drive backward

// We can also augment Car to include all functions from our mixin
// by not explicitly listing a selection of them
augment( Car, Mixin );

var mySportsCar = new Car({
    model: "Porsche",
    color: "red"
});

mySportsCar.driveSideways();

// Outputs:
// drive sideways

優(yōu)點&缺點

Mixin支持在一個系統(tǒng)中降解功能的重復性,增加功能的重用性.在一些應用程序也許需要在所有的對象實體共享行為的地方,我們能夠通過在一個Mixin中維護這個共享的功能,來很容易的避免任何重復,而因此專注于只實現我們系統(tǒng)中真正彼此不同的功能。

也就是說,對Mixin的副作用是值得商榷的.一些開發(fā)者感覺將功能注入到對象的原型中是一個壞點子,因為它會同時導致原型污染和一定程度上的對我們原有功能的不確定性.在大型的系統(tǒng)中,很可能是有這種情況的。

我認為,強大的文檔對最大限度的減少對待功能中的混入源的迷惑是有幫助的,而且對于每一種模式而言,如果在實現過程中小心行事,我們應該是沒多大問題的。

上一篇:單例模式下一篇:代理模式