设计模式 - Mixin模式

混入(Mixin)是一个对象,我们可以使用它来向另一个对象或类添加可重用的功能,而无需使用继承。我们无法独立使用混入,它的唯一目的是向对象或类添加功能,而不使用继承。

比如说,在我们的应用程序中,我们需要创建多个狗。然而,我们创建的狗的基本类型没有任何属性,只有一个名字属性。

class Dog {
  constructor(name) {
    this.name = name;
  }
}

狗不仅仅应该有一个名字,它还应该能够叫、摇尾巴和玩耍!我们不必直接在Dog类中添加这些行为,而是可以创建一个混入(mixin)来为我们提供叫、摇尾巴和玩耍的属性。

const dogFunctionality = {
  bark: () => console.log("Woof!"),
  wagTail: () => console.log("Wagging my tail!"),
  play: () => console.log("Playing!"),
};

我们可以使用 Object.assign 方法将 dogFunctionality mixin 添加到 Dog 原型中。此方法允许我们向目标对象添加属性:在本例中为 Dog.prototype。每个新的 Dog 实例都可以访问 dogFunctionality 的属性,因为它们被添加到Dog 的原型中!

class Dog {
  constructor(name) {
    this.name = name;
  }
}

const dogFunctionality = {
  bark: () => console.log("Woof!"),
  wagTail: () => console.log("Wagging my tail!"),
  play: () => console.log("Playing!"),
};

Object.assign(Dog.prototype, dogFunctionality);

让我们创建我们的第一只宠物 pet1,名为 Daisy。由于我们刚刚将 dogFunctionality mixin 添加到Dog的原型中,Daisy 应该能够走路、摇尾巴和玩耍!

const pet1 = new Dog("Daisy");

pet1.name; // Daisy
pet1.bark(); // Woof!
pet1.play(); // Playing!

Mixins 让我们可以轻松地在不使用继承的情况下向类或对象添加自定义功能。

虽然我们可以在不继承的情况下使用 mixin 添加功能,但 mixin 本身可以使用继承!

大多数哺乳动物(除了海豚,也许还有更多)也可以走路和睡觉。狗是哺乳动物,应该会走路和睡觉!让我们创建一个 animalFunctionality mixin,它添加了 walk 和 sleep 属性。

const animalFunctionality = {
  walk: () => console.log("Walking!"),
  sleep: () => console.log("Sleeping!"),
};

我们可以使用 Object.assign 将这些属性添加到 dogFunctionality 原型中。在本例中,目标对象为 dogFunctionality

const animalFunctionality = {
  walk: () => console.log("Walking!"),
  sleep: () => console.log("Sleeping!"),
};

const dogFunctionality = {
  bark: () => console.log("Woof!"),
  wagTail: () => console.log("Wagging my tail!"),
  play: () => console.log("Playing!"),
  walk() {
    super.walk();
  },
  sleep() {
    super.sleep();
  },
};

Object.assign(dogFunctionality, animalFunctionality);
Object.assign(Dog.prototype, dogFunctionality);

现在,Dog 实例都可以访问walksleep方法。

在浏览器环境中的 Window 界面上可以看到现实世界中的 mixin 示例。Window 对象从 WindowOrWorkerGlobalScope 和 WindowEventHandlers 混合中实现其许多属性,这使我们能够访问 setTimeout 和 setIntervalindexedDB 和 isSecureContext 等属性。

由于它是一个 mixin,因此仅用于向对象添加功能,因此您将无法创建 WindowOrWorkerGlobalScope 类型的对象。

window.indexedDB.open("toDoList");

window.addEventListener("beforeunload", event => {
  event.preventDefault();
  event.returnValue = "";
});

window.onbeforeunload = function() {
  console.log("Unloading!");
};

console.log(
  "From WindowEventHandlers mixin: onbeforeunload",
  window.onbeforeunload
);

console.log(
  "From WindowOrWorkerGlobalScope mixin: isSecureContext",
  window.isSecureContext
);

console.log(
  "WindowEventHandlers itself is undefined",
  window.WindowEventHandlers
);

console.log(
  "WindowOrWorkerGlobalScope itself is undefined",
  window.WindowOrWorkerGlobalScope
);

React(ES6 之前)

在引入 ES6 类之前,Mixin 通常用于为 React 组件添加功能。React 团队不鼓励使用 mixin,因为它很容易给组件增加不必要的复杂性,使其难以维护和重用。React 团队鼓励使用高阶组件,这些组件现在通常可以被 Hooks 取代。

Mixins 允许我们通过将功能注入对象的原型来轻松地向对象添加功能,而无需继承。但修改对象的原型被视为不好的做法,因为它可能导致原型污染和我们功能来源的一定程度的不确定性。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值