Personal-Study/Design Patterns
[TS Design Patterns] 생성 패턴 - 팩토리 메서드
Aaron-Kim
2023. 10. 21. 20:22
Factory Method (Virtual Constructor)
- Provides an interface of creating objects in a superclass,
but allows subclasses to alter the type of objects that will be created
- Suggests that we replace direct object construction calls (using the new operator)
with calls to a special factory method
- Creator, Sub Classes
- Sovles the problem of creating product objects without specifying their concrete classes
- 팩토리 패턴
- 객체를 생성하는 팩토리 함수 사용
- 함수 호출하는 것으로 객체 만들어냄
-> new 키워드 사용하는 대신 함수 호출의 결과로 객체 만들어냄
- 상대적으로 복잡한 객체 또는 환경이나 설정에 따라 키와 값을 다양하게 설정해야 하는 객체 만들 때 유용
- 특정한 키나 값을 가진 객체 쉽게 만들어 냄
- 동일한 프로퍼티를 가진 여러 작은 객체 만들어낼 때 유용함
- 대부분 상황에서 객체를 일일히 만드는 것보다 클래스를 활용하는 것이 메모리 절약에 효과적임
- 예시
/**
* The Creator class declares the factory method that is supposed to return an
* object of a Product class. The Creator's subclasses usually provide the
* implementation of this method.
*/
abstract class Creator {
/**
* Note that the Creator may also provide some default implementation of the
* factory method.
*/
public abstract factoryMethod(): Product;
/**
* Also note that, despite its name, the Creator's primary responsibility is
* not creating products. Usually, it contains some core business logic that
* relies on Product objects, returned by the factory method. Subclasses can
* indirectly change that business logic by overriding the factory method
* and returning a different type of product from it.
*/
public someOperation(): string {
// Call the factory method to create a Product object.
const product = this.factoryMethod();
// Now, use the product.
return `Creator: The same creator's code has just worked with ${product.operation()}`;
}
}
/**
* Concrete Creators override the factory method in order to change the
* resulting product's type.
*/
class ConcreteCreator1 extends Creator {
/**
* Note that the signature of the method still uses the abstract product
* type, even though the concrete product is actually returned from the
* method. This way the Creator can stay independent of concrete product
* classes.
*/
public factoryMethod(): Product {
return new ConcreteProduct1();
}
}
class ConcreteCreator2 extends Creator {
public factoryMethod(): Product {
return new ConcreteProduct2();
}
}
/**
* The Product interface declares the operations that all concrete products must
* implement.
*/
interface Product {
operation(): string;
}
/**
* Concrete Products provide various implementations of the Product interface.
*/
class ConcreteProduct1 implements Product {
public operation(): string {
return '{Result of the ConcreteProduct1}';
}
}
class ConcreteProduct2 implements Product {
public operation(): string {
return '{Result of the ConcreteProduct2}';
}
}
/**
* The client code works with an instance of a concrete creator, albeit through
* its base interface. As long as the client keeps working with the creator via
* the base interface, you can pass it any creator's subclass.
*/
function clientCode(creator: Creator) {
// ...
console.log(
"Client: I'm not aware of the creator's class, but it still works."
);
console.log(creator.someOperation());
// ...
}
/**
* The Application picks a creator's type depending on the configuration or
* environment.
*/
console.log('App: Launched with the ConcreteCreator1.');
clientCode(new ConcreteCreator1());
console.log('');
console.log('App: Launched with the ConcreteCreator2.');
clientCode(new ConcreteCreator2());
const createUser = ({ firstName, lastName, email }) => ({
firstName,
lastName,
email,
fullName() {
return `${this.firstName} ${this.lastName}`;
}
});
const user1 = createUser({
firstName: "John",
lastName: "Doe",
email: "john@doe.com"
});
const user2 = createUser({
firstName: "Jane",
lastName: "Doe",
email: "jane@doe.com"
});
console.log(user1);
console.log(user2);
- 활용
반응형