+TypeScript 예제
TypeScript에서도 같은 두 역할을 나눈다. 위 UML의 Send·Deliver는 아래 코드의 send·deliver에 대응하며, 생성자로 채널을 전달하는 구조는 같다.
// 알림 쪽이 문자·메일의 구체 API를 몰라도 메시지를 건넬 수 있는 약속이다.
interface IChannel {
deliver(message: string): string;
}
// 실제 전송 대신 어느 채널을 골랐는지 문자열로 보여 준다.
class SmsChannel implements IChannel {
deliver(message: string): string { return "SMS: " + message; }
}
class MailChannel implements IChannel {
deliver(message: string): string { return "MAIL: " + message; }
}
abstract class Notice {
protected readonly channel: IChannel;
constructor(channel: IChannel) {
// 생성자로 받은 채널을 보관한다. 알림 종류와 전달 방식을 여기서 연결한다.
this.channel = channel;
}
abstract send(message: string): string;
}
class NormalNotice extends Notice {
override send(message: string): string {
return this.channel.deliver(message);
}
}
class UrgentNotice extends Notice {
override send(message: string): string {
// 긴급 문구는 알림 규칙이므로 채널마다 복사하지 않고 이곳에서 붙인다.
return this.channel.deliver("URGENT " + message);
}
}
// 채널만 교체하면서 같은 두 알림 종류를 재사용한다.
for (const channel of [new SmsChannel(), new MailChannel()]) {
console.log(new NormalNotice(channel).send("ready"));
console.log(new UrgentNotice(channel).send("ready"));
}
SMS: ready
SMS: URGENT ready
MAIL: ready
MAIL: URGENT ready
새 채널이 deliver()를 구현하면 NormalNotice와 UrgentNotice에 그대로 연결할 수 있다. 반대로 알림 종류를 추가해도 기존 채널을 수정할 필요가 없다.