Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript设计模式-Mixin模式 #52

Open
bojue opened this issue Oct 4, 2019 · 0 comments
Open

JavaScript设计模式-Mixin模式 #52

bojue opened this issue Oct 4, 2019 · 0 comments
Labels
设计模式 Design Patterns

Comments

@bojue
Copy link
Owner

bojue commented Oct 4, 2019

JavaScript设计模式-Mixin模式

JavaScript没有类似概念,无法在语言层面实现类的继承和多态等行为,JavaScript只有对象,一个对象无法直接复制到其他对象。JavaScript的Mixin(混入)模式是为了模拟类的复制行为。

显示混入

在包含类的类C语言中(Python,C++,Java)定义了类的概念,通过类的继承或者多重继承,子类对象复制了父类定义的属性和方法。

在JavaScript语言中,Mixin的显示混入是模拟类的多重继承的机制。

function minxin(sourceObj, targetObj, rewriteBool) {
    if(!(sourceObj && targetObj)) return ;
    for(let key in sourceObj) {
        if(rewriteBool) {
            targetObj[key] = sourceObj[key];
        } else if(!(key in targetObj)){
            targetObj[key] = sourceObj[key];
        }
    }
    return targetObj;
}

let Aircraft = {
    name: '飞机',
    manufacturer: '中国直升机设计研究所',
    flight: function() {
        console.log(`${this.name} 是飞机!`)
    },
    introduction: function() {
        console.log(`简介: 由 ${this.manufacturer} 研制!`)
    }
}

let HelicopterFlight = minxin(Aircraft, {
    name: 'AV500直升机',
    flight:function () {
        Aircraft.flight.call(this),
        console.log(`${this.name} 使用螺旋桨提供动力!` )
    }
})

HelicopterFlight.flight();
HelicopterFlight.introduction();

我们封装了自己的minxin核心代码,这个方法包含了数据源对象(sourceObj),目标对象(targetObj,),覆盖( rewriteBool)三个参数,通过对数据源对象的属性和方法的遍历,依次复制到目标对象,实现目标对象对数据源对象的复制,rewriteBool参数控制是否允许sourceObj对targetObj对象的相同属性和方法的重写。

Mixin的方法的复制不是函数的复制,而是对函数引用的简单复制,即sourceObj和targetObj的方法是同一个函数的引用。

隐式混入

Mixin的隐式混入,是通过this的重新绑定的机制实现。

let Aircraft = {
    name: '飞机',
    manufacturer: '中国直升机设计研究所',
    flight: function() {
        console.log(`${this.name} 是飞机!`)
    }
}

let HelicopterFlight =  {
    name: 'AV500直升机',
    flight:function () {
        Aircraft.flight.call(this)
    }
}

HelicopterFlight.flight();

在HelicopterFlight上下文调用Aircraft.flight(),赋值发生在 HelicopterFlight对象上与Aircraft对象无关。

寄生继承

寄生继承是显示继承的一种变体。

function Aircraft() {
    this.name = '飞机'
}

Aircraft.prototype.flight = function() {
    console.log(`名称: ${this.name}`)
}

function HelicopterFlight() {
    let air = new Aircraft();
    air.name = "AV500";
    air.manufacturer = '中国直升机设计研究所';

    let dir = air.flight;
    
    air.flight = function () {
        dir.call(this);
        console.log(`简介: ${this.name}${this.manufacturer}, 研发` )
    }
    return air;
}

let helicopterFlight = new HelicopterFlight();
helicopterFlight.flight()

我们使用new常见HelicopterFlight新的的对象并绑定this到新对象上,在这个新对象上我们实现在自己的额外操作然后返回新对象。

在HelicopterFlight内部通过this绑定实现在HelicopterFlight上下文中对Aircraft.flight()函数的调用。

所以说寄生模式是显示绑定和也是隐式绑定。

参考

@bojue bojue added blog blog Web 设计模式 Design Patterns and removed blog blog Web labels Oct 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
设计模式 Design Patterns
Projects
None yet
Development

No branches or pull requests

1 participant