admin管理员组

文章数量:1246502

I was reading about different methods of object creation in JavaScript instead of using new and ES6-classes. One method is using the factory method/factory class pattern (taken from ):

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

How would I implement a class like Animal or rather another factory funtion which my dog function can "inherit" from? Would I pass the animal object to the dog function and set the prototype of the object being returned to the passed animal object?

I was reading about different methods of object creation in JavaScript instead of using new and ES6-classes. One method is using the factory method/factory class pattern (taken from https://medium./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"

How would I implement a class like Animal or rather another factory funtion which my dog function can "inherit" from? Would I pass the animal object to the dog function and set the prototype of the object being returned to the passed animal object?

Share Improve this question edited May 9, 2017 at 7:55 eol asked May 9, 2017 at 7:49 eoleol 24.6k6 gold badges51 silver badges70 bronze badges 4
  • 1 What is it that you're trying to achieve exactly? You might not need inheritance. – nils Commented May 9, 2017 at 7:55
  • Just use extends: developer.mozilla/en-US/docs/Web/JavaScript/Reference/… – Inspiraller Commented May 9, 2017 at 8:06
  • Just asking in general but for example the Animal class could implement behaviour which all of its subclasses would want to implement. Or a method like move() which would be overwritten in some of the subclasses. – eol Commented May 9, 2017 at 8:07
  • Because this is not the “factory pattern” I’m looking for. – Константин Ван Commented May 8, 2022 at 8:10
Add a ment  | 

4 Answers 4

Reset to default 9

You would use Object.create:

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();

BTW, my opinion is that you should go with ES2015+ class/inheritance and leave the use of custom factories and Object.create for corner cases where you really need them:

class Animal {
  talk() {
    return console.log(this.sound);
  }
}

class Dog extends Animal {
  constructor() {
    super();
    this.sound = "woof";
  }
}

var dog = new Dog();
dog.talk();

I checked this issue because I decided to use Factory Functions instead of classes. I assume you have a general factory function, like Animal or Mammal, which has some characteristics (such as sound, like some suggested), and you want to inherit them and add some specific characteristic in another factory function.

Let's build an Animal factory function:

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"

And let's build a Dog factory function:

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!"

What should I do if I want to inherit all the good things I get from Animal that I have already?
Using ES6 Spread Syntax helps us to achieve a very neat way of doing so:

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!"

So what actually happened?
In Dog factory we invoked the Animal factory into anAnimal, so anAnimal is now an object. In the object that Dog factory returns, we spread the anAnimal object, and after that added properties of Dog. If you give an Object two identical keys with different values, it will take the latter:

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

Therefore, you don't need to worry if Dog uses any keys that were given already from Animal, because they are overwritten.

@nils is right, it's not clear what/why you want to inherit, so I'm just guessing, but maybe this is what you mean :)

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

In addition to these other answers, I'd remend taking a look at this excellent book on Javascript design patterns, Learning JavaScript Design Patterns.

In particular, take a look at its chapter on factories.

To achieve inheritance in a factory pattern, its original factory class accepts a configuration object. More specific factories just extend the original factory class by passing in objects.

本文标签: javascriptInheritance with factory methodclass patternStack Overflow