带有类但没有 Mixins 的 Javascript 中的组合模式?
Posted
技术标签:
【中文标题】带有类但没有 Mixins 的 Javascript 中的组合模式?【英文标题】:Composition Pattern in Javascript with Classes but without Mixins? 【发布时间】:2021-11-09 19:48:39 【问题描述】:以下是在 javascript 中实现组合模式的有效策略吗?我想使用类而不是构造函数或普通对象,而且我知道 Mixins 不是最佳实践。一个问题是,在这种方法中,添加到Person
对象的方法没有附加到原型,因此每个方法都需要内存分配。谢谢!
class Person
name;
constructor(name)
this.name = name;
function fly()
return
fly()
console.log(`$this.name can fly!`);
,
;
function swim()
return
swim()
console.log(`$this.name can swim!`);
,
;
function makeFlyingPerson(name)
return Object.assign(new Person(name), fly());
function makeSwimmingPerson(name)
return Object.assign(new Person(name), swim());
【问题讨论】:
不过,这仍然是 mixins。您将两个对象混合在一起 - 一个对象的方法/属性被添加到另一个对象。 如果它按照您想要的方式工作,它就是有效的。也就是说,我认为fly
、swim
等没有任何理由成为函数,正如@VLAZ 指出的那样,这个 is 混合。说到:“而且我知道 Mixins 不是最佳实践” 为什么不呢?根据谁?
如果您使用 Class 语法的动机是为了简化 Java 和 JavaScript 之间的大脑切换,我建议您的代码对于试图理解这一点的 Java 开发人员来说会非常混乱。如果这是您的目标,那么请一直使用 Class 语法,以便其他人可以轻松掌握它。 FWIW。
@r_zelazny ... 对于提供的示例,任何 mixin 支持技术只有在 OP 实际上不希望每个人实例具有飞行和游泳行为/特征时才有意义。否则Person.prototype
仍然是分配此类行为的最佳位置。在这种情况下,稍后通过将所需行为直接混入原型中来增强已经实现的Person
类的原型是完全有效的。
【参考方案1】:
...添加到
Person
对象的方法未附加到原型,因此每个方法都需要分配内存
没错,但这是一个微不足道的数量,每个对象每个方法的一个属性的成本(保存该方法的函数引用)。属性不是什么都没有,但它们并不大。为免生疑问:function 对象被所有实例重用,而不是复制。
fly
和 swim
没有理由成为函数,但(至少,从问题中看不出),直接使用对象:
class Person
name;
constructor(name)
this.name = name;
const flyMethods =
fly()
console.log(`$this.name can fly!`);
,
;
const swimMethods =
swim()
console.log(`$this.name can swim!`);
,
;
function makeFlyingPerson(name)
return Object.assign(new Person(name), flyMethods);
function makeSwimmingPerson(name)
return Object.assign(new Person(name), swimMethods);
请注意,这仍然使用 mixins(您的原始版本和上述版本)。
除非您打算将fly
/flyMethods
和swim
/swimMethods
与Person
以外的其他类一起重用,否则使用extends
似乎更简单,并且会给您提供原型方法重用:
class FlyingPerson extends Person
fly()
// ...
如果您正在在多个类中重用fly
/flyMethods
等,另一种选择是使用工厂构建函数从各种方法集创建原型,然后重复使用它:
class Person
name;
constructor(name)
this.name = name;
const flyMethods =
fly()
console.log(`$this.name can fly!`);
,
;
const swimMethods =
swim()
console.log(`$this.name can swim!`);
,
;
function extendWith(cls, name, ...mixins)
// We use the wrapper object so that the class constructor's name is assigned from `name`
const obj =
[name]: class extends cls
;
Object.assign(obj[name].prototype, ...mixins);
return obj[name];
const FlyingPerson = extendWith(Person, "FlyingPerson", flyMethods);
const SwimmingPerson = extendWith(Person, "SwimmingPerson", swimMethods);
const FlyingSwimmingPerson = extendWith(Person, "FlyingSwimmingPerson", flyMethods, swimMethods);
const joe = new FlyingSwimmingPerson("Joe");
joe.fly();
joe.swim();
class Animal
name;
type;
constructor(name, type)
this.name = name;
this.type = type;
const FlyingSwimmingAnimal = extendWith(Animal, "FlyingSwimmingAnimal", flyMethods, swimMethods);
console.log(FlyingSwimmingAnimal.name); // FlyingSwimmingAnimal
const splippery = new FlyingSwimmingAnimal("Slippery");
splippery.fly();
splippery.swim();
【讨论】:
我想知道 OP 问题中的这一点。哪一点对 OP 更重要 - 开发人员沟通或内聚/最小耦合。 如果应该增强对象,这些函数会更有意义,例如,flyer = obj => obj.fly = fly
。然后允许一个人制作flier(person)
甚至swimmer(flier(person))
来获得两者。当然,只有对象,这可以是Object.assign(person, swimMethods, flyMethods)
。
感谢您的回答!
@r_zelazny - 我的荣幸!我已将其添加到 FWIW 的末尾。编码愉快!以上是关于带有类但没有 Mixins 的 Javascript 中的组合模式?的主要内容,如果未能解决你的问题,请参考以下文章