Singleton 패턴
Singleton 패턴은 애플리케이션 내에서 단 하나의 인스턴스만을 가지도록 보장하는 디자인 패턴이다. 이 패턴을 사용하면 전역 변수를 사용하지 않고, 객체 인스턴스를 공유하여 리소스를 절약할 수 있다.
Singleton 패턴을 구현하는 방법은 다음과 같다.
Singleton 클래스 생성
Singleton 패턴을 구현하기 위해, 먼저 Singleton 클래스를 생성한다. 이 클래스는 단 하나의 인스턴스만을 가질 수 있도록, private 생성자를 가지고 있다.
class Singleton {
private static instance: Singleton;
private constructor() {}
public static getInstance(): Singleton {
if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
}
getInstance() 메소드 생성
getInstance() 메소드는 Singleton 인스턴스를 반환하는 정적 메소드다. 이 메소드는 Singleton 인스턴스가 생성되어 있는지 확인하고, 생성되어 있지 않다면 인스턴스를 생성한다. 생성된 인스턴스는 클래스의 private static 변수에 저장된다.
Singleton 인스턴스 사용
Singleton 인스턴스는 getInstance() 메소드를 호출하여 가져올 수 있다. 이 인스턴스는 전역에서 공유되므로, 모든 코드에서 동일한 인스턴스를 사용할 수 있다.
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true
위 예제에서는 Singleton 클래스를 생성하고, getInstance() 메소드를 구현했다. getInstance() 메소드는 Singleton 인스턴스를 생성하여 private static 변수에 저장하고, 이를 반환한다. Singleton 인스턴스는 전역에서 공유되므로, instance1과 instance2는 동일한 인스턴스를 참조한다.
Singleton 패턴은 애플리케이션 내에서 단 하나의 인스턴스만을 가지도록 보장함으로써, 객체 인스턴스의 리소스를 절약할 수 있다. 또한, 전역 변수를 사용하지 않고 객체 인스턴스를 공유하므로, 코드의 유지보수성과 확장성을 향상시킨다.
Observer 패턴
Observer 패턴은 객체 간의 일대다 의존성을 정의하는 디자인 패턴이다. 이 패턴을 사용하면, 어떤 객체의 상태가 변경되었을 때, 이를 관찰하는 다른 객체들에게 자동으로 알릴 수 있다.
Observer 패턴을 구현하는 방법은 다음과 같다.
Subject 클래스 생성
Subject 클래스는 옵저버를 등록하고, 상태를 변경할 때 옵저버들에게 알린다. 이 클래스에는 옵저버를 등록하는 메소드와 상태를 변경하고 알림을 보내는 메소드가 필요하다.
class Subject {
private observers: Observer[] = [];
private state: string;
public attach(observer: Observer): void {
this.observers.push(observer);
}
public detach(observer: Observer): void {
const index = this.observers.indexOf(observer);
if (index > -1) {
this.observers.splice(index, 1);
}
}
public setState(state: string): void {
this.state = state;
this.notify();
}
public getState(): string {
return this.state;
}
private notify(): void {
for (const observer of this.observers) {
observer.update();
}
}
}
Observer 클래스 생성
Observer 클래스는 Subject 객체의 상태가 변경되었을 때, 알림을 받는 인터페이스다. 이 클래스에는 상태 변경 시 처리해야 할 로직이 구현된 update() 메소드가 필요하다.
interface Observer {
update(): void;
}
class ConcreteObserverA implements Observer {
private subject: Subject;
constructor(subject: Subject) {
this.subject = subject;
this.subject.attach(this);
}
public update(): void {
console.log(`ConcreteObserverA: ${this.subject.getState()}`);
}
}
class ConcreteObserverB implements Observer {
private subject: Subject;
constructor(subject: Subject) {
this.subject = subject;
this.subject.attach(this);
}
public update(): void {
console.log(`ConcreteObserverB: ${this.subject.getState()}`);
}
}
Observer 객체 등록 및 상태 변경
Observer 객체를 등록하고, 상태가 변경되었을 때 옵저버들에게 알린다.
const subject = new Subject();
const observerA = new ConcreteObserverA(subject);
const observerB = new ConcreteObserverB(subject);
subject.setState("new state");
위 예제에서는 Subject 클래스와 Observer 인터페이스를 생성하고, ConcreteObserverA와 ConcreteObserverB 클래스를 구현했다. 이후 Subject 객체를 생성하고, Observer 객체를 등록한다. 마지막으로, 상태를 변경하면 Subject 객체는 등록된 옵저버들에게 자동으로 알린다.
Observer 패턴을 사용하면 객체 간의 의존성을 낮추고, 애플리케이션을 더욱 유연하고 확장성 있는 구조로 만들 수 있다. 또한, 상태 변경 시 자동으로 알림을 보내므로, 애플리케이션의 무결성과 일관성을 보장할 수 있다.
Strategy 패턴
Strategy 패턴은 알고리즘군을 정의하고, 각각을 캡슐화하여 상호교환 가능하도록 만드는 디자인 패턴이다. 이 패턴을 사용하면, 실행 중에 알고리즘을 선택하고 변경할 수 있으며, 이를 통해 유연성과 확장성 있는 애플리케이션을 만들 수 있다.
Strategy 패턴을 구현하는 방법은 다음과 같다.
Strategy 인터페이스 생성
Strategy 인터페이스는 알고리즘을 캡슐화하는 인터페이스다. 이 인터페이스에는 알고리즘을 수행하는 메소드가 포함된다.
interface Strategy {
execute(): void;
}
ConcreteStrategy 클래스 생성
ConcreteStrategy 클래스는 Strategy 인터페이스를 구현하는 클래스다. 각 ConcreteStrategy 클래스는 고유한 알고리즘을 구현한다.
class ConcreteStrategyA implements Strategy {
public execute(): void {
console.log("Executing strategy A");
}
}
class ConcreteStrategyB implements Strategy {
public execute(): void {
console.log("Executing strategy B");
}
}
Context 클래스 생성
Context 클래스는 Strategy 객체를 사용하는 클래스다. 이 클래스에는 현재 선택된 Strategy 객체가 저장된다. 또한, Strategy 객체를 변경하는 메소드가 필요하다.
class Context {
private strategy: Strategy;
constructor(strategy: Strategy) {
this.strategy = strategy;
}
public setStrategy(strategy: Strategy): void {
this.strategy = strategy;
}
public executeStrategy(): void {
this.strategy.execute();
}
}
Strategy 객체 생성 및 실행
ConcreteStrategyA와 ConcreteStrategyB 객체를 생성하고, 이를 Context 객체에 주입하여 실행한다.
const context = new Context(new ConcreteStrategyA());
context.executeStrategy();
context.setStrategy(new ConcreteStrategyB());
context.executeStrategy();
위 예제에서는 Strategy 인터페이스를 생성하고, ConcreteStrategyA와 ConcreteStrategyB 클래스를 구현했다. 이후 Context 클래스를 생성하고, ConcreteStrategyA 객체를 주입하여 실행한다. 이후 Context 객체에 ConcreteStrategyB 객체를 주입하여 실행한다.
Strategy 패턴을 사용하면, 각각의 알고리즘을 개별적인 객체로 캡슐화하므로, 알고리즘의 수정 및 추가가 용이하다. 또한, Context 객체는 실행 중에 Strategy 객체를 변경할 수 있으므로, 애플리케이션을 보다 유연하게 구성할 수 있다.
Factory Method 패턴
Factory Method 패턴은 객체를 생성하는 메소드를 추상화하여 객체 생성을 캡슐화하는 패턴이다. 이 패턴은 다른 클래스들이 객체를 생성할 때 사용되며, 객체의 생성을 추상화함으로써 유연성과 확장성을 제공한다.
타입스크립트에서 Factory Method 패턴을 구현하는 방법은 다음과 같다.
Abstract Factory 클래스 생성
Factory Method 패턴에서는 객체를 생성하는 메소드를 추상화하기 위해 추상 팩토리 클래스를 생성한다. 이 클래스는 객체를 생성하는 메소드를 가지고 있으며, 이 메소드는 추상 메소드다.
abstract class AnimalFactory {
abstract createAnimal(): Animal;
}
구체적인 Factory 클래스 생성
Abstract Factory 클래스를 상속받아 구체적인 Factory 클래스를 생성한다. 이 클래스에서는 추상 메소드를 구체화하여 객체를 생성하는 구체적인 로직을 구현한다.
class DogFactory extends AnimalFactory {
createAnimal(): Animal {
return new Dog();
}
}
class CatFactory extends AnimalFactory {
createAnimal(): Animal {
return new Cat();
}
}
객체 생성
구체적인 Factory 클래스에서 createAnimal() 메소드를 호출하여 객체를 생성한다.
const dogFactory = new DogFactory();
const dog = dogFactory.createAnimal(); // new Dog()
const catFactory = new CatFactory();
const cat = catFactory.createAnimal(); // new Cat()
위 예제에서는 AnimalFactory라는 추상 팩토리 클래스를 생성하고, 이를 상속받은 DogFactory와 CatFactory 클래스를 구현했다. 각각의 클래스에서는 createAnimal() 메소드를 구현하여 Dog 객체와 Cat 객체를 생성한다.
Factory Method 패턴은 객체 생성을 캡슐화함으로써 객체 생성에 대한 유연성과 확장성을 제공한다. 새로운 객체를 추가하려면 새로운 Factory 클래스를 생성하기만 하면 되므로 코드의 유지보수 및 확장이 용이하다. 또한, 추상화된 팩토리 클래스를 사용하므로 코드의 결합도가 낮아지며, 유닛 테스트가 용이하다.
Factory 패턴
Factory 패턴은 객체를 생성하는 공장을 만들고, 이를 사용하여 객체를 생성하는 디자인 패턴이다. 이 패턴을 사용하면 객체 생성에 대한 복잡성을 감소시키고, 유연성과 확장성을 높일 수 있다.
Factory 패턴을 구현하는 방법은 다음과 같다.
Creator 클래스 생성
Creator 클래스는 객체를 생성하는 추상 클래스다. 이 클래스는 팩토리 메소드를 선언하고, 객체를 생성하는 책임을 갖는다.
abstract class Creator {
public abstract factoryMethod(): Product;
public someOperation(): string {
const product = this.factoryMethod();
return `Creator: The same creator's code has just worked with ${product.operation()}`;
}
}
Product 인터페이스 생성
Product 인터페이스는 팩토리 메소드가 생성할 객체의 인터페이스다. 이 인터페이스는 객체가 갖는 메소드를 정의한다.
interface Product {
operation(): string;
}
ConcreteProduct 클래스 생성
ConcreteProduct 클래스는 Product 인터페이스를 구현하는 클래스다. 이 클래스는 실제 객체를 생성한다.
class ConcreteProductA implements Product {
public operation(): string {
return '{Result of ConcreteProductA}';
}
}
class ConcreteProductB implements Product {
public operation(): string {
return '{Result of ConcreteProductB}';
}
}
ConcreteCreator 클래스 생성
ConcreteCreator 클래스는 Creator 클래스를 상속받는 클래스다. 이 클래스는 팩토리 메소드를 구현하고, ConcreteProduct 객체를 생성한다.
class ConcreteCreatorA extends Creator {
public factoryMethod(): Product {
return new ConcreteProductA();
}
}
class ConcreteCreatorB extends Creator {
public factoryMethod(): Product {
return new ConcreteProductB();
}
}
객체 생성
ConcreteCreatorA와 ConcreteCreatorB 객체를 생성하고, 각각의 factoryMethod 메소드를 사용하여 ConcreteProductA와 ConcreteProductB 객체를 생성한다.
const creatorA = new ConcreteCreatorA();
console.log(creatorA.someOperation());
const creatorB = new ConcreteCreatorB();
console.log(creatorB.someOperation());
위 예제에서는 Creator 클래스와 Product 인터페이스를 생성하고, ConcreteProductA와 ConcreteProductB 클래스를 구현했다. 이후 ConcreteCreatorA와 ConcreteCreatorB 클래스를 생성하고, 각각의 factoryMethod 메소드를 사용하여 ConcreteProductA와 ConcreteProductB 객체를 생성한다.
Factory 패턴을 사용하면 객체 생성 로직을 캡슐화하여 유연성과 확장성을 높일 수 있다. 또한, 객체 생성 로직의 변경이 필요할 때 해당 로직만 변경하면 되므로, 코드 유지보수가 용이하다.
Factory Method 패턴 & Factory 패턴
Factory Method 패턴과 Factory 패턴 모두 객체 생성을 위한 패턴이지만, 차이점이 존재한다.
Factory Method 패턴은 객체 생성을 하위 클래스에게 위임하는 패턴이다.
Factory Method 패턴은 객체를 생성하기 위한 인터페이스를 정의하고, 구체적인 클래스의 인스턴스 생성을 하위 클래스에서 구현한다. 이를 통해 객체 생성 로직을 변경하고, 유연하게 대처할 수 있다. 예를 들어, Abstract Factory 패턴에서는 공장을 추상화하여 다양한 제품군을 생성할 수 있다. 이 패턴은 여러 개의 Factory Method 패턴을 적용한 것이다.
Factory 패턴은 객체를 생성하는 클래스를 정의하는 패턴이다.
Factory 패턴은 객체 생성의 책임을 특정 클래스에 위임하는 방식으로 작동한다. 이 클래스는 일반적으로 인스턴스화된 객체를 생성하는 정적 메서드를 제공한다. 이를 통해 객체 생성 로직을 캡슐화하여 유지보수 및 재사용성을 높일 수 있다.
Factory Method 패턴과 Factory 패턴은 둘 다 객체 생성을 캡슐화하고, 유지보수 및 재사용성을 높이는 데 도움을 준다. 그러나 Factory Method 패턴은 하위 클래스에게 객체 생성을 위임하는 것에 중점을 두고, Factory 패턴은 객체 생성을 위한 클래스를 정의하는 것에 중점을 둡니다.