static create
패턴이 유용한 상황
대부분의 경우 생성자를 사용하는 것이 더 직관적이고 단순하지만, 다음과 같은 상황에서는 static create
가 더 적합
- 생성 로직이 복잡하거나 조건부 처리가 필요할 때
- 팩토리 패턴을 간소화하고 싶을 때
- 생성 과정에서의 불변성을 강화하고 싶을 때
- 다른 타입을 반환하거나, 실패 가능성을 명시적으로 처리하고 싶을 때
1. 생성 로직 커스터마이징
- 생성자가 단순히 필드 초기화만 수행하는 경우는 일반 생성자로 충분하지만, 생성 과정에서 유효성 검사, 값 변환, 혹은 복잡한 비즈니스 로직이 필요하다면
static create
패턴이 더 적합 - 예를 들어, 유효성 검사를 통과하지 못하면 객체를 반환하지 않거나, 에러를 던질 수 있음
- 생성 과정에서의 제약 조건을 명시적으로 처리할 수 있음
class User {
private constructor(private readonly name: string) {}
static create(name: string): User | null {
if (!name || name.length < 3) {
console.error('Invalid name!')
return null
}
return new User(name)
}
}
const validUser = User.create('John') // 성공
const invalidUser = User.create('Jo') // 실패, null 반환
2. 팩토리 패턴의 간소화
static create
를 간단한 팩토리 메서드로 활용해서 객체 생성의 복잡성을 숨기기- 객체의 생성 방식이 호출자의 관점에서는 중요하지 않다면 내부 로직을 캡슐화할 수 있다
- 이런 방식은 타입에 따라 다른 구현체를 생성해야 하는 경우
class Shape {
static create(type: 'circle' | 'rectangle', size: number): Shape {
if (type === 'circle') {
return new Circle(size)
} else {
return new Rectangle(size)
}
}
}
3. 불변성 및 제약 강화
- 생성자를
private
로 설정하고,static
메서드만을 통해 객체를 생성하도록 제한하면 객체의 불변성을 더 강하게 유지할 수 있다 - 특정 조건에 따라 객체의 생성을 제한하거나 실패하도록 설계할 수 있다
class CardNumber {
private constructor(private readonly number: string) {}
static create(number: string): CardNumber | null {
if (!CardNumber.isValid(number)) {
return null
}
return new CardNumber(number)
}
private static isValid(number: string): boolean {
return number.length === 16
}
}
const card = CardNumber.create('1234567812345678') // 유효한 카드
const invalidCard = CardNumber.create('123') // null
4. 다른 타입 반환
생성자는 항상 해당 클래스의 인스턴스만 반환할 수 있다. 반면, static create
는 경우에 따라 다른 타입의 값을 반환할 수 있다.
class Result<T> {
private constructor(
public readonly value: T | null,
public readonly error: string | null
) {}
static success<T>(value: T): Result<T> {
return new Result(value, null)
}
static failure<T>(error: string): Result<T> {
return new Result(null, error)
}
}
class User {
private constructor(private readonly name: string) {}
static create(name: string): Result<User> {
if (!name || name.length < 3) {
return Result.failure('Name must be at least 3 characters long')
}
return Result.success(new User(name))
}
}
const result = User.create('Jo') // 실패 결과 반환
5. 객체 재사용
동일한 인스턴스를 재사용하고 싶을 때도 static create
패턴이 적합하다. 예를 들어, 싱글톤(Singleton) 패턴처럼 동작하거나 캐싱된 객체를 반환할 수 있다.
class Configuration {
private static instance: Configuration
private constructor(public readonly settings: Record<string, string>) {}
static create(): Configuration {
if (!Configuration.instance) {
Configuration.instance = new Configuration({ mode: 'production' })
}
return Configuration.instance
}
}
const config1 = Configuration.create()
const config2 = Configuration.create()
console.log(config1 === config2) // true