Programing

생성자 함수 대 팩토리 함수

lottogame 2020. 6. 23. 07:41
반응형

생성자 함수 대 팩토리 함수


누군가 Javascript에서 생성자 함수와 팩토리 함수의 차이점을 명확히 할 수 있습니까?

다른 하나 대신 사용할 때?


기본적인 차이점은 생성자 함수가 new키워드 와 함께 사용된다는 것입니다 (JavaScript는 새 오브젝트를 자동으로 작성 this하고 함수 내에서 해당 오브젝트로 설정 한 후 오브젝트를 리턴합니다).

var objFromConstructor = new ConstructorFunction();

팩토리 함수는 "일반적인"함수와 같습니다.

var objFromFactory = factoryFunction();

그러나 "공장"으로 간주 되려면 일부 객체의 새 인스턴스를 반환해야합니다. 부울 또는 무언가를 반환 한 경우 "공장"함수라고 부르지 않습니다. 이와 같이 자동으로 발생하지는 않지만 new경우에 따라 더 많은 융통성을 허용합니다.

실제로 간단한 예에서 위에서 참조한 함수는 다음과 같습니다.

function ConstructorFunction() {
   this.someProp1 = "1";
   this.someProp2 = "2";
}
ConstructorFunction.prototype.someMethod = function() { /* whatever */ };

function factoryFunction() {
   var obj = {
      someProp1 : "1",
      someProp2 : "2",
      someMethod: function() { /* whatever */ }
   };
   // other code to manipulate obj in some way here
   return obj;
}

물론 간단한 예제보다 팩토리 기능을 훨씬 더 복잡하게 만들 수 있습니다.

어떤 사람들은 사용을 기억할 필요가 없기 때문에 모든 것에 팩토리 함수를 사용하는 것을 선호합니다 new(편집 : new함수가 없으면 실행되지만 예상대로 작동 하지 않기 때문에 문제가 될 수 있습니다 ). 나는 그것을 장점으로 보지 않는다 new. 언어의 핵심 부분이므로 의도적으로 언어를 피하는 것은 약간 임의적 else이다.

팩토리 함수의 장점 중 하나는 리턴 될 오브젝트가 일부 매개 변수에 따라 여러 유형이 될 수 있다는 것입니다.


생성자 사용의 이점

  • 대부분의 책은 생성자를 사용하고 new

  • this 새로운 객체를 참조

  • 어떤 사람들은 var myFoo = new Foo();읽는 방식을 좋아합니다 .

단점

  • 인스턴스화의 세부 사항이 new요구 사항을 통해 호출 API로 유출 되므로 모든 호출자가 생성자 구현에 밀접하게 연결됩니다. 공장의 추가 유연성이 필요한 경우 모든 발신자를 리팩토링해야합니다 (규칙이 아닌 예외적 인 경우 임).

  • 잊어 버리는 new것은 일반적인 버그이므로 생성자가 올바르게 호출되도록 상용구 검사를 추가하는 것이 좋습니다 ( if (!(this instanceof Foo)) { return new Foo() }). 편집 : ES6 (ES2015)를 잊지 수 없기 때문에 newclass생성자, 또는 생성자 오류가 발생합니다.

  • 당신이 할 경우 instanceof확인 여부에 관해서는 모호성을 잎 new이 필요합니다. 내 의견으로는,해서는 안됩니다. new요구 사항을 효과적으로 단축했습니다. 즉, 단점 1을 지울 수 있습니다. 그러나 추가 상용구, 대문자 및 덜 유연한 컨텍스트 와 함께 name 이외의 팩토리 함수가this 있습니다.

생성자는 개방 / 폐쇄 원칙을 어기다

그러나 나의 주요 관심사는 그것이 공개 / 폐쇄 원칙을 위반한다는 것입니다. 생성자 내보내기를 시작하고 사용자가 생성자를 사용하기 시작한 다음 대신 팩토리의 유연성이 필요하다는 것을 깨달았습니다 (예 : 구현을 전환하여 객체 풀을 사용하거나 실행 컨텍스트를 통해 인스턴스화하거나 프로토 타입 OO를 사용하여 더 많은 상속 유연성을 갖습니다).

그래도 당신은 붙어 있습니다. 로 생성자를 호출하는 모든 코드를 중단하지 않고는 변경할 수 없습니다 new. 예를 들어 성능 향상을 위해 객체 풀을 사용하도록 전환 할 수 없습니다.

또한 생성자를 사용하면 instanceof실행 컨텍스트에서 작동하지 않는 속임수 제공 하며 생성자 프로토 타입이 교체되면 작동하지 않습니다. this생성자에서 반환을 시작한 다음 임의의 개체 내보내기로 전환하면 생성자에서 팩토리와 같은 동작을 수행해야합니다.

공장 사용의 이점

  • 코드가 적고 보일러 플레이트가 필요하지 않습니다

  • 임의의 객체를 반환하고 임의의 프로토 타입을 사용할 수 있으므로 동일한 API를 구현하는 다양한 유형의 객체를 생성 할 수있는 유연성이 향상됩니다. 예를 들어 HTML5 및 플래시 플레이어의 인스턴스를 만들 수있는 미디어 플레이어 또는 DOM 이벤트 또는 웹 소켓 이벤트를 생성 할 수있는 이벤트 라이브러리가 있습니다. 또한 팩토리는 실행 컨텍스트에서 객체를 인스턴스화하고 객체 풀을 활용하며보다 유연한 프로토 타입 상속 모델을 허용 할 수 있습니다.

  • 팩토리에서 생성자로 변환 할 필요가 없으므로 리팩토링은 문제가되지 않습니다.

  • 사용에 대한 모호함이 없습니다 new. 하지마 (이것은 this나쁘게 행동 할 것입니다 , 다음 요점을보십시오).

  • this behaves as it normally would - so you can use it to access the parent object (for example, inside player.create(), this refers to player, just like any other method invocation would. call and apply also reassign this, as expected. If you store prototypes on the parent object, that can be a great way to dynamically swap out functionality, and enable very flexible polymorphism for your object instantiation.

  • No ambiguity about whether or not to capitalize. Don't. Lint tools will complain, and then you'll be tempted to try to use new, and then you'll undo the benefit described above.

  • Some people like the way var myFoo = foo(); or var myFoo = foo.create(); reads.

Drawbacks

  • new doesn't behave as expected (see above). Solution: don't use it.

  • this doesn't refer to the new object (instead, if the constructor is invoked with dot notation or square bracket notation, e.g. foo.bar() - this refers to foo - just like every other JavaScript method -- see benefits).


A constructor returns an instance of the class you call it on. A factory function can return anything. You would use a factory function when you need to return arbitrary values or when a class has a large setup process.


A Constructor function example

function User(name) {
  this.name = name;
  this.isAdmin = false;
}

let user = new User("Jack");
  • new creates an object prototyped on User.prototype and calls User with the created object as its this value.

  • new treats an argument expression for its operand as optional:

       let user = new User;
    

    would cause new to call User with no arguments.

  • new returns the object it created, unless the constructor returns an object value, which is returned instead. This is an edge case which for the most part can be ignored.

Pros and Cons

Objects created by constructor functions inherit properties from the constructor's prototype property, and return true using the instanceOf operator on the constructor function.

The above behaviors can fail if you dynamically change the value of the constructor's prototype property after having already used the constructor. Doing so is rare, and it can't be changed if the constructor were created using the class keyword.

Constructor functions can be extended using the extends keyword.

Constructor functions can't return null as an error value. Since it's not an object data type, it is ignored by new.

A Factory function example

function User(name, age) {
  return {
    name,
    age,
  }
};

let user = User("Tom", 23);

Here the factory function is called without new. The function is entirely responsible for the direct or indirect use if its arguments and the type of object it returns. In this example it returns a simple [Object object] with some properties set from arguments.

Pros and Cons

Easily hides the implementation complexities of object creation from the caller. This is particularly useful for native code functions in a browser.

The factory function need not always return objects of the same type, and could even return null as an error indicator.

In simple cases, factory functions can be simple in structure and meaning.

Objects returned do not generally inherit from the factory function's prototype property, and return false from instanceOf factoryFunction.

The factory function can't be safely extended using the extends keyword because extended objects would inherit from the factory functions prototype property instead of from the prototype property of the constructor used by the factory function.


Factories are "always" better. When using object orientated languages then

  1. decide on the contract (the methods and what they will do)
  2. Create interfaces that expose those methods (in javascript you don't have interfaces so you need to come up with some way of checking the implementation)
  3. Create a factory that returns an implementation of each interface required.

The implementations (the actual objects created with new) are not exposed to the factory user/consumer. This means that the factory developer can expand and create new implementations as long as he/she doesn't break the contract...and it allows for the factory consumer to just benefit from the new API without having to change their code...if they used new and a "new" implementation comes along then they have to go and change every line which uses "new" to use the "new" implementation...with the factory their code doesn't change...

Factories - better than all anything else - the spring framework is completely built around this idea.


Factories are a layer of abstraction, and like all abstractions they have a.cost in complexity. When encountering a factory based API figuring out what the factory is for a given API can be challenging for the API consumer. With constructors discoverability is trivial.

When deciding between ctors and factories you need to decide if the complexity is justified by the benefit.

Worth noting that Javascript constructors can be arbitrary factories by returning something other than this or undefined. So in js you can get the best of both worlds - discoverable API and object pooling/caching.


For the differences, Eric Elliott clarified very well,

But for the second question:

When to use one instead of the other?

If you are coming from the object-oriented background, Constructor function looks more natural to you. this way you shouldn't forget to use new keyword.

참고URL : https://stackoverflow.com/questions/8698726/constructor-function-vs-factory-functions

반응형