+ );
+}
+```
+
+### 관찰자 패턴 vs 발행/구독 패턴
+
+관찰자 패턴은 발행자와 구독자가 서로를 알고 있어야 하지만 발행/구독 패턴은 그것을 중계해주는 채널이 있어서 발행자와 구독자는 서로를 몰라도 된다고 함
+유튜브로 예를 들면 위의 관찰자 예시는 유튜버가 구독자가 누군지 알고 있는 형태
+발행/구독 패턴의 경우 유튜버는 유튜브 플랫폼에다 영상 열심히 올리기만 하고, 유튜브 플랫폼이 새로운 영상 받으면 알아서 구독자에게 알려주는 역할
+
+
+## 중재자 패턴
+
+갑자기 여기서 플라이웨이트 패턴때 설명했던 이벤트 위임을 얘기하는데, 그래서 이벤트 위임은 어디에 해당한다는 건지...?
+중재자 패턴과 발행/구독 패턴이 비슷하게 느껴짐. 둘 다 소통하는 객체 사이에 통신을 중개하는 레이어를 두는 것이 특징인 것 같다.
+어떻게 다른지 구체적으로 알고싶어서 클로드한테 물어봄
+
+발행/구독 패턴:
+1. 유튜버는 그냥 영상을 올립니다. 누가 볼지 신경 쓰지 않죠.
+2. 구독자들은 그냥 채널을 구독합니다. 다른 구독자가 누군지 모릅니다.
+3. 유튜브 플랫폼은 단순히 "이 채널에 새 영상이 올라왔어요"라고 알려주기만 합니다.
+
+```javascript
+// 발행/구독 예시
+class YouTube {
+ constructor() {
+ this.channels = new Map(); // { 채널명: [구독자들] }
+ }
+
+ subscribe(channelName, subscriber) {
+ if (!this.channels.has(channelName)) {
+ this.channels.set(channelName, []);
+ }
+ this.channels.get(channelName).push(subscriber);
+ }
+
+ // 단순히 알림만 전달
+ notify(channelName, video) {
+ const subscribers = this.channels.get(channelName) || [];
+ subscribers.forEach(subscriber => {
+ subscriber.update(`${channelName}에 새 영상이 업로드됨: ${video}`);
+ });
+ }
+}
+```
+
+중재자 패턴:
+1. 메시지를 보낼 때 특정 사람을 지정할 수 있습니다.
+2. 귓속말도 가능합니다.
+3. 카카오톡 서버는 "누가 누구에게" 보내는지 알고 있고, 그에 따라 다르게 처리합니다.
+4. 방장 권한, 강퇴, 초대 등 복잡한 규칙이 있습니다.
+
+```javascript
+// 중재자 예시
+class KakaoTalkRoom {
+ constructor() {
+ this.users = new Map();
+ this.admin = null;
+ }
+
+ // 복잡한 규칙들을 관리
+ sendMessage(from, message, to = null) {
+ if (this.isBanned(from)) {
+ return this.notify(from, "당신은 차단된 사용자입니다.");
+ }
+
+ if (to) {
+ // 귓속말
+ this.sendPrivateMessage(from, to, message);
+ } else {
+ // 전체 메시지
+ this.broadcastMessage(from, message);
+ }
+ }
+
+ kickUser(admin, userToKick) {
+ if (this.admin !== admin) {
+ return this.notify(admin, "방장만 강퇴할 수 있습니다.");
+ }
+ // 강퇴 로직...
+ }
+}
+```
+
+둘의 차이
+1. **복잡도**
+ - 발행/구독: 단순한 알림 전달만 함 (유튜브 알림처럼)
+ - 중재자: 복잡한 규칙과 로직이 있음 (카카오톡 방처럼)
+
+2. **방향성**
+ - 발행/구독: 일방적인 알림 (유튜버 → 구독자)
+ - 중재자: 양방향 소통 (카톡방 사람들끼리)
+
+3. **규칙**
+ - 발행/구독: 거의 없음 ("구독하면 알림 받음" 정도)
+ - 중재자: 많음 (방장 권한, 귓속말, 강퇴 등)
+
+그렇다고 한다.
+책보다 클로드한테 물어보는게 더 이해가 잘되는 듯.
+
+책의 설명을 조금 곁들이자면,
+이벤트 집합 패턴(발행/구독): 실행되어야 하는 모든 비즈니스 로직은 이벤트 발생 객체와 처리 객체에 직접 구현된다.
+중재자 패턴: 모든 비즈니스 로직이 중재자 내부에 집중된다.
+
+## 커맨드 패턴
+
+이것도 책 예시가 조금 불친절한 것 같아서 자세히 알아보기 위해 클로드를 활용
+책 설명을 보니까 abstract 클래스를 쓰면 편할 것 같아 타입스크립트로 만들어보라고 함
+
+```typescript
+// 추상 커맨드 클래스
+abstract class Command {
+ abstract execute(): void;
+ abstract undo(): void;
+}
+
+// Receiver: TV
+class TV {
+ private isOn: boolean = false;
+
+ turnOn(): void {
+ this.isOn = true;
+ console.log('TV가 켜졌습니다.');
+ }
+
+ turnOff(): void {
+ this.isOn = false;
+ console.log('TV가 꺼졌습니다.');
+ }
+
+ getStatus(): boolean {
+ return this.isOn;
+ }
+}
+
+// Concrete Command: TV 전원 커맨드
+class PowerCommand extends Command {
+ constructor(private tv: TV) {
+ super();
+ }
+
+ execute(): void {
+ if (this.tv.getStatus()) {
+ this.tv.turnOff();
+ } else {
+ this.tv.turnOn();
+ }
+ }
+
+ undo(): void {
+ this.execute(); // 전원은 토글이므로 같은 동작
+ }
+}
+
+// Invoker: 리모컨
+class RemoteControl {
+ private history: Command[] = [];
+
+ pressButton(command: Command): void {
+ command.execute();
+ this.history.push(command);
+ }
+
+ undo(): void {
+ const command = this.history.pop();
+ if (command) {
+ command.undo();
+ }
+ }
+}
+
+// 사용 예시
+const tv = new TV();
+const powerCommand = new PowerCommand(tv);
+const remote = new RemoteControl();
+
+remote.pressButton(powerCommand); // TV 켜기
+remote.pressButton(powerCommand); // TV 끄기
+remote.undo(); // 마지막 동작 취소
+```
+
+
+실생활에서 TV 리모컨을 사용할 때를 생각해보세요. 리모컨의 버튼을 누르면 TV가 그에 맞는 동작을 수행합니다. 이때 리모컨은 TV의 내부 동작 방식을 전혀 알 필요가 없습니다. 단지 "이 버튼을 누르면 이런 일이 일어난다"는 것만 알면 됩니다.
+커맨드 패턴의 구성 요소를 리모컨의 관점에서 보면:
+
+1. **추상 Command 클래스**
+ - 모든 리모컨 버튼의 기본 형태를 정의합니다.
+ - execute()와 undo() 라는 두 가지 추상 메서드를 가집니다.
+ - 마치 리모컨 버튼의 설계도와 같습니다.
+
+2. **TV (Receiver)**
+ - 실제로 작동하는 기기입니다.
+ - 자신이 할 수 있는 기능들을 가지고 있습니다 (전원 켜기/끄기).
+ - 누가 자신을 제어하는지는 알 필요가 없습니다.
+
+3. **PowerCommand (Concrete Command)**
+ - 실제 리모컨의 전원 버튼과 같습니다.
+ - TV를 알고 있어서 TV에게 적절한 명령을 내릴 수 있습니다.
+ - execute()는 TV의 현재 상태에 따라 켜거나 끄는 동작을 수행합니다.
+ - undo()는 이전 상태로 되돌리는 동작을 수행합니다.
+
+4. **RemoteControl (Invoker)**
+ - 실제 리모컨 본체입니다.
+ - 버튼들의 명령을 실행하고 기록을 관리합니다.
+ - 어떤 버튼이 어떤 동작을 하는지만 알면 됩니다.
+
+이 패턴의 가장 큰 장점은 각 부분이 서로 독립적이라는 것입니다:
+
+1. **분리된 책임**
+ - TV는 자신의 기능만 구현하면 됩니다.
+ - 리모컨은 명령을 전달하기만 하면 됩니다.
+ - 각 명령은 자신의 동작만 알면 됩니다.
+
+2. **유연한 확장**
+ - 새로운 기능을 추가하려면 새로운 Command 클래스만 만들면 됩니다.
+ - 기존 코드를 수정할 필요가 없습니다.
+
+3. **실행 취소 기능**
+ - 모든 명령이 undo() 메서드를 구현하므로 쉽게 실행 취소가 가능합니다.
+ - 명령의 기록을 저장해두면 여러 단계의 실행 취소도 가능합니다.
+
+타입스크립트의 abstract 클래스를 사용하면:
+1. 모든 커맨드가 반드시 execute()와 undo()를 구현하도록 강제할 수 있습니다.
+2. 컴파일 시점에 타입 체크가 가능합니다.
+3. 코드의 안정성이 높아집니다.
+
+이 패턴은 특히:
+- 실행 취소/다시 실행이 필요할 때
+- 명령을 큐에 저장해야 할 때
+- 명령의 실행을 지연시키고 싶을 때
+매우 유용하게 사용됩니다.
+