Command 패턴
Command 패턴은 객체 지향 디자인 패턴 중 하나로, 어떤 작업을 수행하는 명령(Command)을 캡슐화하여 실행할 수 있는 객체로 만들고, 이를 조합하여 원하는 기능을 수행하는 방식을 제공하는 패턴이다.
타입스크립트에서는 Command 패턴을 구현하기 위해 다음과 같은 단계를 따른다.
Command 인터페이스 정의하기
Command 인터페이스는 명령(Command)을 수행하는 메소드 execute를 가지고 있다. 이 인터페이스를 구현하는 클래스들은 execute 메소드를 구현하여 각각의 명령을 수행한다.
interface Command {
execute(): void;
}
Command 구현하기
Command 인터페이스를 구현하여 각각의 명령(Command)을 구현한다. 이때 각 명령(Command)은 수행할 작업을 캡슐화한 객체로 만들어진다.
class TurnOnCommand implements Command {
private readonly light: Light;
constructor(light: Light) {
this.light = light;
}
execute(): void {
this.light.turnOn();
}
}
Invoker 구현하기
Invoker는 명령(Command)을 실행하는 객체이다. 이 객체는 execute 메소드를 가지며, 이 메소드는 전달받은 명령(Command)을 실행한다.
class RemoteControl {
private command?: Command;
setCommand(command: Command): void {
this.command = command;
}
pressButton(): void {
if (this.command) {
this.command.execute();
}
}
}
Client 코드 작성하기
Client 코드에서는 Command 객체를 생성하고, 이를 Invoker 객체에 전달하여 실행한다.
const light = new Light();
const turnOnCommand = new TurnOnCommand(light);
const remoteControl = new RemoteControl();
remoteControl.setCommand(turnOnCommand);
remoteControl.pressButton(); // Light를 켭니다.
이렇게 Command 패턴을 구현하면, 여러 개의 명령(Command)을 조합하여 다양한 기능을 구현할 수 있다.
Composite 패턴
Composite 패턴은 객체지향 디자인 패턴 중 하나로, 객체들을 트리 구조로 구성하여 부분-전체 계층을 표현하는 패턴이다. 이 패턴은 일반적으로 객체들 간의 유사성을 활용하여 복잡한 구조를 쉽게 처리할 수 있도록 한다.
타입스크립트에서 Composite 패턴을 구현하려면 다음과 같은 단계를 따른다.
Component 인터페이스 생성하기
Component 인터페이스는 모든 객체에 공통적인 인터페이스를 제공한다. 이 인터페이스는 복합 객체와 단일 객체 모두가 구현해야 한다.
interface Component {
operation(): void;
}
Leaf 클래스 생성하기
Leaf 클래스는 복합 객체에서 단일 객체를 나타낸다. Leaf 클래스는 Component 인터페이스를 구현하며, 자신이 표현하는 객체의 동작을 정의한다.
class Leaf implements Component {
public operation(): void {
// Leaf 동작 정의
}
}
Composite 클래스 생성하기
Composite 클래스는 복합 객체에서 내부에 다른 Component 객체들을 가지는 객체를 나타낸다. Composite 클래스는 Component 인터페이스를 구현하며, 자신이 포함하는 Component 객체들의 동작을 정의한다.
class Composite implements Component {
private children: Component[] = [];
public add(component: Component): void {
this.children.push(component);
}
public remove(component: Component): void {
const componentIndex = this.children.indexOf(component);
this.children.splice(componentIndex, 1);
}
public operation(): void {
for (const child of this.children) {
child.operation();
}
}
}
코드 사용하기
이제 Leaf와 Composite 클래스를 사용하여 복잡한 구조를 표현할 수 있다.
const composite = new Composite();
const leaf1 = new Leaf();
const leaf2 = new Leaf();
composite.add(leaf1);
composite.add(leaf2);
composite.operation();
위의 예제에서는 Composite 객체가 두 개의 Leaf 객체를 포함하는 구조를 만들었다. Composite 객체의 operation() 메소드가 호출되면, Composite 객체는 자식 객체들의 operation() 메소드를 호출한다. 따라서 leaf1과 leaf2의 operation() 메소드가 호출되어 동작을 수행한다.
이처럼 Composite 패턴을 사용하면 객체들 간의 유사성을 활용하여 복잡한 구조를 쉽게 처리할 수 있도록 한다.
Facade 패턴
Facade 패턴은 객체지향 디자인 패턴 중 하나로, 복잡한 서브시스템을 간단한 인터페이스를 통해 사용할 수 있도록 추상화하는 패턴이다. 이 패턴은 복잡한 서브시스템과 사용자 사이의 인터페이스를 제공하여, 서브시스템의 복잡도를 감소시키고 사용자가 더 쉽게 사용할 수 있도록 한다.
타입스크립트에서 Facade 패턴을 구현하려면 다음과 같은 단계를 따른다.
Facade 클래스 생성하기
Facade 클래스는 서브시스템의 복잡도를 감소시키기 위한 단순한 인터페이스를 제공한다. Facade 클래스는 서브시스템의 복잡도를 처리하고 감추는 역할을 한다.
class Facade {
private subsystem1: Subsystem1;
private subsystem2: Subsystem2;
constructor() {
this.subsystem1 = new Subsystem1();
this.subsystem2 = new Subsystem2();
}
public operation(): void {
this.subsystem1.operation1();
this.subsystem2.operation2();
}
}
Subsystem 클래스 생성하기
Subsystem 클래스는 서브시스템을 구성하는 객체들을 나타낸다. Subsystem 클래스는 Facade 클래스에서 사용되며, 서브시스템의 구현을 캡슐화한다.
class Subsystem1 {
public operation1(): void {
// 서브시스템1 동작 정의
}
}
class Subsystem2 {
public operation2(): void {
// 서브시스템2 동작 정의
}
}
코드 사용하기
이제 Facade 클래스와 Subsystem 클래스를 사용하여 서브시스템을 처리할 수 있다. Facade 클래스는 Subsystem1과 Subsystem2 객체를 생성하고, Facade 클래스의 operation() 메소드가 호출되면 Subsystem1의 operation1() 메소드와 Subsystem2의 operation2() 메소드가 호출된다.
const facade = new Facade();
facade.operation();
위의 예제에서는 Facade 객체를 생성하고, Facade 객체의 operation() 메소드를 호출하여 Subsystem1과 Subsystem2 객체의 동작을 수행한다.
Facade 클래스를 사용하면 Subsystem 클래스의 복잡도를 감소시키고, 사용자가 서브시스템을 더 쉽게 사용할 수 있도록 한다.
Flyweight 패턴
Flyweight 패턴은 객체지향 디자인 패턴 중 하나로, 객체의 공유를 통해 메모리 사용량을 줄이는 패턴이다. 이 패턴은 많은 수의 비슷한 객체를 생성할 때, 중복된 데이터를 공유하여 메모리 사용량을 줄이고 성능을 향상시킨다.
타입스크립트에서 Flyweight 패턴을 구현하려면 다음과 같은 단계를 따른다.
Flyweight 인터페이스 생성하기
Flyweight 인터페이스는 공유할 객체의 인터페이스를 정의한다. 이 인터페이스는 공유할 객체에 필요한 메소드를 선언한다.
interface Flyweight {
operation(): void;
}
Flyweight 클래스 생성하기
Flyweight 클래스는 Flyweight 인터페이스를 구현하는 객체를 나타낸다. 이 클래스는 중복된 데이터를 공유하고, 객체 생성 비용을 최소화한다.
class ConcreteFlyweight implements Flyweight {
private intrinsicState: any;
constructor(intrinsicState: any) {
this.intrinsicState = intrinsicState;
}
public operation(): void {
// intrinsicState에 따른 동작 정의
}
}
Flyweight Factory 클래스 생성하기
Flyweight Factory 클래스는 Flyweight 객체를 생성하고 관리한다. 이 클래스는 Flyweight 객체를 캐싱하여 중복된 객체 생성을 방지하고, 공유할 객체를 반환한다.
class FlyweightFactory {
private flyweights: { [key: string]: Flyweight } = {};
public getFlyweight(key: string): Flyweight {
if (!this.flyweights[key]) {
this.flyweights[key] = new ConcreteFlyweight(key);
}
return this.flyweights[key];
}
}
코드 사용하기
이제 Flyweight Factory 클래스를 사용하여 Flyweight 객체를 생성하고 관리할 수 있다. Flyweight Factory 클래스의 getFlyweight() 메소드를 호출하여 공유할 Flyweight 객체를 얻을 수 있다.
const factory = new FlyweightFactory();
const flyweight1 = factory.getFlyweight("key1");
const flyweight2 = factory.getFlyweight("key2");
위의 예제에서는 Flyweight Factory 객체를 생성하고, getFlyweight() 메소드를 호출하여 공유할 Flyweight 객체를 얻는다.
Flyweight Factory 클래스를 사용하면 많은 수의 비슷한 객체를 생성할 때 메모리 사용량을 줄이고 성능을 향상시킬 수 있다.
Proxy 패턴
Proxy 패턴은 객체지향 디자인 패턴 중 하나로, 객체의 대리자 역할을 하는 프록시 객체를 통해 다른 객체에 대한 접근을 제어하는 패턴이다. 이 패턴은 객체의 접근 제어, 캐싱, 로깅 등 다양한 목적으로 사용된다.
타입스크립트에서 Proxy 패턴을 구현하려면 다음과 같은 단계를 따른다.
Proxy 인터페이스 생성하기
Proxy 인터페이스는 대리자 역할을 하는 객체의 인터페이스를 정의한다. 이 인터페이스는 프록시 객체와 실제 객체가 공유하는 메소드를 선언한다.
interface Proxy {
request(): void;
}
RealSubject 클래스 생성하기
RealSubject 클래스는 Proxy 인터페이스를 구현하는 실제 객체를 나타낸다. 이 클래스는 프록시 객체에 의해 감싸여 있으며, 실제 객체의 동작을 정의한다.
class RealSubject implements Proxy {
public request(): void {
// 실제 객체의 동작 정의
}
}
Proxy 클래스 생성하기
Proxy 클래스는 Proxy 인터페이스를 구현하는 대리자 역할을 하는 객체를 나타낸다. 이 클래스는 실제 객체에 대한 접근을 제어하고, 프록시 객체를 사용하는 클라이언트의 요청을 처리한다.
class ProxyObject implements Proxy {
private realSubject: RealSubject;
constructor() {
this.realSubject = new RealSubject();
}
public request(): void {
// 프록시 객체의 동작 정의
this.realSubject.request();
}
}
코드 사용하기
이제 Proxy 클래스를 사용하여 RealSubject 객체에 대한 접근을 제어할 수 있다. Proxy 클래스의 request() 메소드를 호출하여 대리자 역할을 하는 객체를 사용할 수 있다.
const proxy = new ProxyObject();
proxy.request();
위의 예제에서는 ProxyObject 객체를 생성하고, request() 메소드를 호출하여 실제 객체인 RealSubject 객체에 대한 접근을 제어한다.
Proxy 패턴은 객체에 대한 접근 제어뿐만 아니라 캐싱, 로깅 등 다양한 목적으로 사용될 수 있다.