기술나눔

소프트웨어 디자인 패턴 요약

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

디자인 패턴은 소프트웨어 디자인의 일반적인 문제에 대한 일반적인 솔루션입니다. 다음은 생성 패턴, 구조 패턴, 동작 패턴이라는 세 가지 주요 범주로 구분된 몇 가지 일반적인 디자인 패턴입니다.

창조 패턴

이러한 패턴은 객체 생성을 위한 메커니즘을 제공하여 기존 코드의 유연성과 재사용성을 높입니다.

  1. 싱글톤 패턴

    • 클래스 인스턴스가 하나만 있는지 확인하고 전역 액세스 지점을 제공하세요.
  2. 팩토리 메소드 패턴

    • 객체 생성을 위한 인터페이스를 정의하고 하위 클래스가 인스턴스화할 클래스를 결정하도록 합니다.
  3. 추상 팩토리 패턴(추상 팩토리)

    • 구체적인 클래스를 명시적으로 지정하지 않고 관련 개체 또는 종속 개체의 패밀리를 만듭니다.
  4. 빌더 패턴(빌더)

    • 복잡한 개체를 만들고 단계별로 구성할 수 있습니다.
  5. 원기

    • 새 인스턴스를 만드는 대신 기존 인스턴스를 복사하여 새 인스턴스를 만듭니다.

구조적 패턴

이러한 패턴은 개체의 조합 또는 개체와 개체 간의 관계를 처리합니다.

  1. 어댑터 모드

    • "어댑터"를 통해 개체 간의 인터페이스 비호환성을 해결할 수 있습니다.
  2. 데코레이터 패턴(Decorator)

    • 객체에 추가 책임을 동적으로 추가합니다.
  3. 프록시 모드(프록시)

    • 다른 개체에 대한 액세스를 제어하기 위한 대체 개체 또는 자리 표시자를 제공합니다.
  4. 정면

    • 하위 시스템의 인터페이스 그룹에 액세스하기 위한 통합된 상위 수준 인터페이스를 제공합니다.
  5. 브리지 모드(브리지)

    • 추상적인 부분을 구현에서 분리하여 독립적으로 변경할 수 있도록 합니다.
  6. 복합 모드

    • 부분-전체 계층 구조를 나타내기 위해 개체를 트리 구조로 그룹화합니다.
  7. 플라이웨이트 모드

    • 공유를 통해 다수의 세분화된 객체를 효율적으로 지원합니다.

행동 패턴

이러한 패턴은 객체 간의 통신, 즉 객체가 상호 작용하고 책임을 분배하는 방식에 중점을 둡니다.

  1. 전략

    • 일련의 알고리즘을 정의하고 하나씩 캡슐화하여 상호 교환 가능하게 만듭니다.
  2. 템플릿 메소드 패턴(Template Method)

    • 메서드에서 알고리즘의 프레임워크를 정의하고 구현을 하위 클래스로 연기합니다.
  3. 옵저버 패턴(Observer)

    • 개체 간의 일대다 종속 관계 개체의 상태가 변경되면 해당 개체에 종속된 모든 개체가 알림을 받고 자동으로 업데이트됩니다.
  4. 반복자 패턴(Iterator)

    • 내부 표현을 노출하지 않고 집계 개체의 개별 요소에 순차적으로 액세스합니다.
  5. 책임 사슬 모델

    • 여러 개체에 요청을 처리할 수 있는 기회를 제공하여 요청 발신자와 수신자 간의 결합을 방지합니다.
  6. 명령 모드(명령)

    • 요청을 객체로 캡슐화하여 사용자가 다양한 요청으로 클라이언트를 매개변수화할 수 있도록 합니다.
  7. 기념품 모드

    • 객체의 내부 상태를 캡처하고 캡슐화를 깨지 않고 이 상태를 객체 외부에 저장합니다.
  8. 상태 모드

    • 내부 상태가 변경되면 개체의 동작을 변경할 수 있습니다.
  9. 방문자 모드

    • 객체 구조(예: 복합 구조)에 새로운 기능을 추가합니다.
  10. 중재자 패턴

    • 원본 객체 간의 상호 작용을 단순화하기 위해 중간 객체를 정의합니다.
  11. 통역사 모드(통역사)

    • 언어의 문법적 표현을 정의하고 해당 언어에 정의된 문장을 해석합니다.

지난 인터뷰에서 코드를 사용하여 구독자-출판자 패턴을 구현하는 방법에 대해 질문을 받았습니다. 이러한 디자인 패턴을 js 코드로 시뮬레이션하는 시간을 가졌습니다.

예를 들어

class PubSub {
  constructor() {
    this.events = {}; // 存储事件名称和对应的订阅者回调函数数组
  }

  // 订阅事件
  subscribe(event, callback) {
    if (!this.events[event]) {
      this.events[event] = []; // 如果事件不存在,初始化一个空数组
    }
    this.events[event].push(callback); // 将回调函数添加到订阅者的数组
  }

  // 取消订阅事件
  unsubscribe(event, callback) {
    if (!this.events[event]) {
      return;
    }
    this.events[event] = this.events[event].filter(cb => cb !== callback); // 移除指定的回调函数
  }

  // 取消特定事件的所有订阅
  unsubscribeAll(event) {
    if (this.events[event]) {
      delete this.events[event]; // 删除所有订阅者
    }
  }

  // 触发事件,使用 emit 作为方法名
  emit(event, data) {
    if (this.events[event]) {
      // 执行所有订阅者的回调函数
      this.events[event].forEach(callback => callback(data));
    }
  }

  // 检查是否有订阅者
  hasSubscribers(event) {
    return this.events[event] && this.events[event].length > 0;
  }
}

// 使用示例
const eventCenter = new PubSub();

// 订阅 'message' 事件
eventCenter.subscribe('message', (data) => {
  console.log(`Message received: ${data}`);
});

// 订阅 'greet' 事件
eventCenter.subscribe('greet', (name) => {
  console.log(`Hello, ${name}!`);
});

// 触发 'message' 事件
eventCenter.emit('message', 'Hello, Pub/Sub!');

// 触发 'greet' 事件
eventCenter.emit('greet', 'World');

// 取消对 'message' 事件的订阅
const myCallback = (data) => {
  console.log(`My callback received: ${data}`);
};
eventCenter.subscribe('message', myCallback);
eventCenter.unsubscribe('message', myCallback);

// 再次触发 'message' 事件,myCallback 不会被调用
eventCenter.emit('message', 'This message will not be received by myCallback');
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

이 예에서는PubSub 클래스는 다음 기능을 제공합니다.

  • subscribe 메소드를 사용하면 구독자가 특정 이벤트에 콜백 함수를 등록할 수 있습니다.
  • unsubscribe 메서드를 사용하면 구독자가 특정 이벤트에서 콜백 함수를 등록 취소할 수 있습니다.
  • unsubscribeAll 메소드는 특정 이벤트에 대한 모든 구독을 취소합니다.
  • emit 이 메서드는 이벤트를 트리거하고 모든 구독자의 콜백 함수를 실행합니다.
  • hasSubscribers 메서드는 특정 이벤트에 대한 구독자가 있는지 확인합니다.