>웹 프론트엔드 >JS 튜토리얼 >소프트웨어 디자인 패턴: 모든 훌륭한 앱 뒤에 숨은 비밀 소스

소프트웨어 디자인 패턴: 모든 훌륭한 앱 뒤에 숨은 비밀 소스

王林
王林원래의
2024-08-24 19:43:02302검색

Software Design Patterns: The Secret Sauce Behind Every Great App

설명서 없이 레고 세트를 만든다고 상상해 보세요. 물론, 막연하게 우주선과 유사한 무언가로 끝날 수도 있지만, 아마도 다채로운 혼돈의 더미로 끝날 가능성이 높습니다. 코딩의 세계에서 디자인 패턴은 LEGO 매뉴얼과 같습니다. 일반적인 문제를 해결하기 위한 입증된 청사진을 제공하여 코드를 더욱 깔끔하고 효율적이며 유지 관리하기 쉽게 만듭니다.

하지만 걱정하지 마세요. 코딩 원리에 대한 무미건조한 강의는 아닙니다. JavaScript의 가장 일반적인 디자인 패턴 중 일부에 대한 재미있는 작은 가이드라고 생각하세요. 이러한 개념을 쉽게 소화할 수 있도록 실제 비유가 포함되어 있습니다.

1. 싱글톤 패턴: 유일무이한 패턴

그것은 무엇입니까?

싱글턴 패턴은 클래스에 인스턴스가 하나만 있도록 보장하고 이에 대한 전역 액세스 지점을 제공합니다. 마치 TV용 리모컨이 하나 있는 것과 같습니다. 볼륨 조절, 채널 변경, 끄기 등에는 여러 개의 리모컨이 필요하지 않습니다. 리모컨 하나만 있으면 됩니다.

실제 사용 사례:

JavaScript에서 이 패턴은 전역 애플리케이션 상태를 관리하는 데 일반적으로 사용됩니다. 예를 들어, 전자 상거래 웹사이트에 장바구니가 있는 경우 장바구니와 상호 작용하는 모든 구성 요소(예: 항목 추가, 항목 제거 또는 결제)가 동일한 장바구니 인스턴스를 참조하기를 원합니다. 싱글톤은 이러한 모든 작업이 다른 복사본이 아닌 동일한 카트에 영향을 미치도록 보장합니다.

class ShoppingCart {
  constructor() {
    if (!ShoppingCart.instance) {
      this.items = [];
      ShoppingCart.instance = this;
    }
    return ShoppingCart.instance;
  }

  addItem(item) {
    this.items.push(item);
  }

  getItems() {
    return this.items;
  }
}

const cart1 = new ShoppingCart();
const cart2 = new ShoppingCart();

cart1.addItem('Laptop');
console.log(cart2.getItems()); // ['Laptop']

2. 관찰자 패턴: 가십 네트워크

그것은 무엇입니까?

관찰자 패턴은 개체를 동기화 상태로 유지하는 것입니다. 한 개체가 변경되면 다른 개체도 이에 대해 알아야 합니다. 모든 사람이 무슨 일이 일어나고 있는지 지속적으로 업데이트되는 그룹 채팅과 같습니다. 누군가 주말 계획을 변경하면 그룹 내 모든 사람이 메모를 받습니다.

실제 사용 사례:

JavaScript에서는 이 패턴이 이벤트 처리 시스템에 자주 사용됩니다. 소셜 미디어 앱을 구축한다고 가정해 보겠습니다. 누군가가 게시물을 좋아하면 좋아요 수를 업데이트하고 게시물 작성자에게 알리고 애니메이션을 트리거할 수도 있습니다. 관찰자 패턴을 사용하면 이러한 다양한 구성 요소를 직접 연결하지 않고도 업데이트 상태를 유지할 수 있습니다.

class Subject {
  constructor() {
    this.observers = [];
  }

  subscribe(observer) {
    this.observers.push(observer);
  }

  unsubscribe(observer) {
    this.observers = this.observers.filter(obs => obs !== observer);
  }

  notify(data) {
    this.observers.forEach(observer => observer.update(data));
  }
}

class Observer {
  update(data) {
    console.log(`Observer received: ${data}`);
  }
}

const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();

subject.subscribe(observer1);
subject.subscribe(observer2);

subject.notify('New post liked!'); 
// Output: Observer received: New post liked!
// Output: Observer received: New post liked!

3. 팩토리 패턴: 쿠키 커터

그것은 무엇입니까?

팩토리 패턴은 생성될 객체의 정확한 클래스를 지정하지 않고 객체를 생성하는 것입니다. 쿠키 커터를 상상해 보세요. 커터를 누르기 전까지는 반죽이 어떤 모양으로 변할지 정확히 알 수 없지만 쿠키가 나올 것이라는 것은 알 수 있습니다.

실제 사용 사례:

이 패턴은 공통 인터페이스나 구조를 공유하지만 기본 구현이 다른 개체 컬렉션이 있는 경우 특히 유용합니다. 예를 들어, 게임에는 다양한 유형의 적(좀비, 뱀파이어, 늑대인간)이 있을 수 있지만 모두 체력, 속도, 공격력과 같은 공통 속성을 공유합니다. 공장은 특정 유형에 대해 걱정하지 않고 이러한 적을 생성하는 데 도움이 될 수 있습니다.

class Enemy {
  constructor(type) {
    this.type = type;
    this.health = 100;
  }

  attack() {
    console.log(`${this.type} attacks with ${this.attackPower}`);
  }
}

class EnemyFactory {
  createEnemy(type) {
    let enemy;

    if (type === 'zombie') {
      enemy = new Enemy('Zombie');
      enemy.attackPower = 10;
    } else if (type === 'vampire') {
      enemy = new Enemy('Vampire');
      enemy.attackPower = 20;
    } else if (type === 'werewolf') {
      enemy = new Enemy('Werewolf');
      enemy.attackPower = 30;
    }

    return enemy;
  }
}

const factory = new EnemyFactory();

const zombie = factory.createEnemy('zombie');
zombie.attack(); // Zombie attacks with 10

const vampire = factory.createEnemy('vampire');
vampire.attack(); // Vampire attacks with 20

4. 모듈 패턴: 정리된 작업 공간

그것은 무엇입니까?

모듈 패턴은 모든 것이 제자리에 있는 잘 정리된 작업 공간을 갖는 것과 같습니다. 이는 코드의 다양한 부분을 정리하고 캡슐화하여 전역 네임스페이스가 어지러워지는 것을 방지하는 데 도움이 됩니다.

실제 사용 사례:

이 패턴은 JavaScript에서 공개 및 비공개 변수와 함수를 생성하는 데 특히 유용합니다. 예를 들어, 라이브러리나 플러그인을 구축할 때 특정 메서드를 외부 세계에 노출하고 다른 메서드는 숨기고 싶을 수 있습니다. 모듈 패턴을 사용하면 바로 이러한 작업이 가능합니다.

const Calculator = (function() {
  let result = 0;

  function add(x) {
    result += x;
    return result;
  }

  function subtract(x) {
    result -= x;
    return result;
  }

  function multiply(x) {
    result *= x;
    return result;
  }

  function divide(x) {
    if (x !== 0) {
      result /= x;
      return result;
    } else {
      console.error('Cannot divide by zero');
    }
  }

  return {
    add,
    subtract,
    multiply,
    divide,
    getResult: () => result,
  };
})();

console.log(Calculator.add(10)); // 10
console.log(Calculator.subtract(2)); // 8
console.log(Calculator.multiply(3)); // 24
console.log(Calculator.divide(4)); // 6

5. 어댑터 패턴: 플러그 변환기

그것은 무엇입니까?

어댑터 패턴을 사용하면 호환되지 않는 인터페이스가 함께 작동할 수 있습니다. 해외여행갈 때 사용하는 플러그 어댑터라고 생각하시면 됩니다. 노트북 충전기의 플러그가 다른 국가의 벽면 콘센트에 맞지 않을 수도 있지만 올바른 어댑터를 사용하면 완벽하게 작동합니다.

실제 사용 사례:

JavaScript에서는 애플리케이션 구조와 정확하게 일치하지 않는 타사 라이브러리 또는 API와 통합할 때 어댑터 패턴을 사용할 수 있습니다. 어댑터는 클래스의 인터페이스를 클라이언트가 기대하는 다른 인터페이스로 변환하여 통합을 원활하게 할 수 있습니다.

class OldApi {
  constructor() {
    this.data = 'Old API data';
  }

  getData() {
    return this.data;
  }
}

class NewApi {
  fetchData() {
    return 'New API data';
  }
}

class ApiAdapter {
  constructor(oldApi) {
    this.oldApi = oldApi;
  }

  fetchData() {
    return this.oldApi.getData();
  }
}

const oldApi = new OldApi();
const adapter = new ApiAdapter(oldApi);

console.log(adapter.fetchData()); // 'Old API data'

6. The Composite Pattern: The Russian Nesting Dolls

What is it?

The Composite pattern allows you to treat individual objects and compositions of objects uniformly. It’s like Russian nesting dolls where each doll is part of a larger structure, but you can interact with them both as individual dolls and as a nested set.

Real-Life Use Case:

This pattern is often used in scenarios where you need to manage a hierarchy of objects. For example, consider a file system where files and folders are represented as objects. A folder can contain multiple files or even other folders, and you want to treat both files and folders similarly when it comes to operations like moving, copying, or deleting.

class File {
  constructor(name) {
    this.name = name;
  }

  display() {
    console.log(this.name);
  }
}

class Folder {
  constructor(name) {
    this.name = name;
    this.children = [];
  }

  add(child) {
    this.children.push(child);
  }

  display() {
    console.log(this.name);
    this.children.forEach(child => child.display());
  }
}

const file1 = new File('file1.txt');
const file2 = new File('file2.txt');
const folder = new Folder('MyFolder');
folder.add(file1);
folder.add(file2);

folder.display();
// Output:
// MyFolder
// file1.txt
// file2.txt

Conclusion

These are just a few of the many design patterns that can make your JavaScript code more robust, maintainable, and, let’s face it, fun to write. Whether you’re building the next big app or just trying to organize your code a bit better, these patterns can be your secret weapon. So next time you’re stuck, remember: there’s probably a pattern for that!

And hey, even if your code doesn’t end up looking like a LEGO spaceship, at least it won’t be a pile of colorful chaos.

Happy coding! ?

위 내용은 소프트웨어 디자인 패턴: 모든 훌륭한 앱 뒤에 숨은 비밀 소스의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
이전 기사:미바의 날: 4일차다음 기사:미바의 날: 4일차