使用工厂方法/类模式继承

时间:2017-05-09 07:49:14

标签: javascript inheritance

我正在阅读JavaScript中不同的对象创建方法,而不是使用new和ES6类。一种方法是使用工厂方法/工厂类模式(取自https://medium.com/humans-create-software/factory-functions-in-javascript-video-d38e49802555):

const dog = () => {
  const sound = 'woof'
  return {
    talk: () => console.log(sound)
  }
}
const sniffles = dog()
sniffles.talk() // Outputs: "woof"

我如何实现像Animal这样的类,或者我的狗功能可以继承的另一种工厂功能"继承"从?我是否会将动物对象传递给dog函数并将对象的原型设置为返回传递的动物对象?

4 个答案:

答案 0 :(得分:5)

您可以使用const animal = () => ({ talk: function() { console.log(this.sound); } }); const dog = () => Object.create(animal(), { sound: { value: "woof" } }); // or... const dog2 = () => { var someDog = Object.create(animal()); someDog.sound = "woof"; return someDog; }; var someDog = dog(); someDog.talk(); var someDog2 = dog2(); someDog2.talk();

Object.create

顺便说一下,我的意见是你应该使用ES2015 +类/继承并将自定义工厂和class Animal { talk() { return console.log(this.sound); } } class Dog extends Animal { constructor() { super(); this.sound = "woof"; } } var dog = new Dog(); dog.talk();用于你真正需要它们的极端情况:

d = {'a' : 
        { 'E' : (x,y) , # EndPoint
          'S' : (x,y) } # StartPoint
}

答案 1 :(得分:2)

@nils是对的,不清楚你想继承什么/为什么,所以我只是猜测,但也许这就是你的意思:)。

const animal = (sound) => {
  return {
    talk: () => console.log(sound)
  }
}
const dog = () => animal('woof')
const sniffles = dog()
sniffles.talk() // Outputs: "woof"

答案 2 :(得分:1)

除了这些其他答案之外,我建议您查看这本关于Javascript设计模式的优秀书籍Learning JavaScript Design Patterns

特别要看一下factories的章节。

要在工厂模式中实现继承,其原始工厂类接受配置对象。更具体的工厂只是通过传入对象来扩展原始工厂类。

答案 3 :(得分:0)

我检查了此问题,因为我决定使用工厂函数而不是类。 我假设您具有一般的工厂功能,例如AnimalMammal,它具有某些特性(例如声音,如建议的一样),并且您想要继承它们并在另一个工厂中添加一些特定的特性功能。

让我们建立一个Animal工厂功能:

const Animal = ({color = "green", numberOfLegs = 4} = {}) => {
  const SetColor = (newColor) => {
    color = newColor;
  };
  const GetColor= () => color;
  const GetNumberOfLegs = () => numberOfLegs;
  const MakeSound = () => console.log("Screetch");
  return {
    GetColor,
    GetNumberOfLegs,
    MakeSound
  }
}
const newCreature = Animal({color: black, numberOfLegs: 3})
newCreature.MakeSound() // -> "Screetch"

让我们构建一个Dog工厂函数:

const Dog = ({name = "rex", color = "black", numberOfLegs = 4} = {}) => {
  const MakeSound = () => console.log("Woof Woof");
  const Roll = () => console.log(`${name} made a roll!`)
  return {
    MakeSound,
    Roll
  }
}
const sniffles = Dog({name: "sniffles", color: black, numberOfLegs: 4})
sniffles.MakeSound() // -> "Woof Woof"
sniffles.Roll() // -> "sniffles made a roll!"

如果我想继承从Animal获得的所有美好的东西,该怎么办?
使用ES6 Spread Syntax可帮助我们实现一种非常整洁的方式:

const Dog = ({name = "rex", color = "black", numberOfLegs = 4} = {}) => {
  const anAnimal = Animal({color, numberOfLegs}); // used the Animal factory!
  const MakeSound = () => console.log("Woof Woof");
  const Roll = () => console.log(`${name} made a roll!`)
  return {
    ...anAnimal, // And That's where magic happens!
    MakeSound,
    Roll
  }
}
const sniffles = Dog({name: "sniffles", color: black, numberOfLegs: 4})
sniffles.GetNumberOfLegs() // -> 4
sniffles.MakeSound() // -> "Woof Woof"
sniffles.Roll() // -> "sniffles made a roll!"

那到底发生了什么?
Dog工厂中,我们在{em> anAnimal 中调用了Animal工厂,因此anAnimal现在是一个对象。 在Dog工厂返回的对象中,我们传播anAnimal对象,然后添加了Dog的属性。 如果为Object提供两个具有不同值的相同键,则将采用后者:

const someObject = {a: 1, b: 2, a: 3};
someObject // -> {a: 3, b: 2}

因此,Dog是否使用Animal中已经提供的任何键,都不必担心,因为它们已被覆盖。