Skip to main content

Mixin Pattern_JavaScript Design Patterns 10

Free2015-08-04#JS#Design_Pattern#JavaScript混入模式#mixin模式#掺入模式#混合模式

Mixin pattern can achieve multiple inheritance, can treat Mixin objects as parts warehouses, can directly install parts from parts warehouse onto existing objects, can conveniently reuse code and enhance existing objects. This article details the Mixin pattern implemented in JavaScript

I. Mixin Pattern and Code Reuse

The most commonly used code reuse method is inheritance, subclasses get all properties of parent class, so may inherit redundant properties. One solution is to split parent class properties into multiple interface classes, subclasses can "self-select" properties needed to inherit from these interface classes, but interfaces in Java are completely abstract (don't contain implementation), cannot achieve code reuse. Using composition can alleviate this problem, but cannot fundamentally solve it, composition needs to hold references to each dependent object, on this basis re-encapsulate and provide interfaces, increasing complexity

If only want to reuse some properties of existing objects, Mixin pattern is undoubtedly the best choice, because completely no need to involve complex class hierarchy relationships. On existing inheritance mechanism, we hope to achieve partial inheritance (only get needed part of properties from parent class) and multiple inheritance (can get properties from multiple parent classes), Mixin pattern does this thing

II. Implementation of Mixin Pattern

Implementation of Mixin pattern is actually a kind of property copying, example code as follows:

// Parts warehouse 1
function Moveable() {}
Moveable.prototype.walk = function() {
    console.log('walked slowly');
}
Moveable.prototype.run = function() {
    console.log('ran quickly');
}
Moveable.prototype.jump = function() {
    // ...
}
// Parts warehouse 2
function Souled() {}
Souled.prototype.smile = function(age) {
    console.log('smiled as ' + age + ' year\'s old kid');
}
// Parts warehouse 3

// mixin
function augment(sub, sup) {
    // Inherit all properties
    if (arguments.length === 2) {
        for(var attr in sup.prototype) {
            sub.prototype[attr] = sup.prototype[attr];
        }
    }
    // Inherit partial properties
    else if(arguments.length > 2) {
        for (var i = 2; i < arguments.length; i++) {
            sub.prototype[arguments[i]] = sup.prototype[arguments[i]];
        }
    }
    else {
        // do nothing
    }
}

// Class needing enhancement
function Robot(name) {
    this.name = name;
}

// Enhance
augment(Robot, Moveable, 'walk', 'run');    // Inherit walk and run from Moveable
augment(Robot, Souled);                     // Inherit all properties of Souled

// test
var robot = new Robot('little boy');
robot.walk();       // walked slowly
robot.run();        // ran quickly
robot.smile(12);    // smiled as 12 year's old kid

Easily achieved partial inheritance and multiple inheritance, released from constraints of classic inheritance mechanism, making code reuse more flexible

Some JS libraries provide Mixin implementation, for example Underscore's _.extend method, JQuery's extend method, YUI's mix/augment/extend/merge methods etc.

III. Disadvantages of Mixin Pattern

Mixin is a very flexible code reuse method, but injecting functionality into prototype objects leads to prototype pollution and uncertainty in function source, may be a serious problem in large systems. Can solve function source uncertainty problem through detailed documentation, but prototype pollution is unavoidable

References

Comments

No comments yet. Be the first to share your thoughts.

Leave a comment