diff --git "a/\354\261\225\355\204\260_7/\354\213\240\354\212\271\354\244\200.md" "b/\354\261\225\355\204\260_7/\354\213\240\354\212\271\354\244\200.md" new file mode 100644 index 0000000..0b3f4af --- /dev/null +++ "b/\354\261\225\355\204\260_7/\354\213\240\354\212\271\354\244\200.md" @@ -0,0 +1,184 @@ +# 자바스크립트 디자인 패턴 + +## 생성자 패턴 + +생성자는 객체가 새로 만들어진 뒤 초기화하는 데에 사용되는 특별한 메서드 + +### 객체 생성 + +```javascript +const newObject = {}; +const newObject = new Object(); +``` + +> 자바스크립트 처음 배울 때 {} 이것보다 new Object()를 썼던 것 같아요. new Object()를 쓰면 이것이 객체라도 더 명확하게 말해줄 수 있지 않나? 싶었던... + +### 모듈 패턴 + +서로 다른 모듈 간의 클래스 또는 함수명 충돌을 방지할 수 있다. + +```html + + + + + + Document + + + + + + +``` + +newObject 변수가 충돌됨. + +### 싱글톤 패턴 + +> ex. 한 나라에는 한 번에 하나의 대통령만 존재할 수 있다. 업무를 할 때마다 동일한 대통령이 행동에 나서야 한다. 여기에서 대통령은 싱글톤이다. + +클래스의 인스턴스가 오직 하나만 존재하도록 제한하는 패턴 + +```javacript +class President { + private static instance: President; + + private constructor() { + // 생성자 숨기기 + } + + public static getInstance(): President { + if (!President.instance) { + President.instance = new President(); + } + + return President.instance; + } + + private clone(): void { + // 복제 비활성화 + } + + private wakeup(): void { + // 데이터 역직렬화(unserialize) 비활성화 + } +} + +const president1: President = President.getInstance(); +const president2: President = President.getInstance(); + +console.log(president1 === president2); // true +``` + +필요할 때까지는 리소스나 메모리를 소모하지 않도록 지연 생성할 수 있다. + +> 책에서는 싱글톤을 사용하지 말라고 하는 것 같네요. + +> 종종 authorized axios instance, unauthorized axios instance 등등 싱글톤으로 몇 가지 인스턴스를 만들고 주구장창 가져다 쓰곤 했는데요, 이 방식에 대해 어떻게 생각하시나요? 그냥 axios 쓰는 것과, createInstance로 인스턴스를 만들어서 그걸 가져다 쓰는 방식 중에서 다들 어떻게 하고 계신지..! + +### 프로토타입 패턴 + +> ex. 복제된 양! 돌리(dolly) + +생성할 객체의 유형이 원형 인스턴스에 의해 결정되며, 이를 복제하여 새로운 객체를 생성한다. + +```javascript +class Sheep { + protected name: string; + protected category: string; + + constructor(name: string, category: string = 'Mountain Sheep') { + this.name = name; + this.category = category; + } + + setName(name: string): void { + this.name = name; + } + + getName(): string { + return this.name; + } + + setCategory(category: string): void { + this.category = category; + } + + getCategory(): string { + return this.category; + } + +const original: Sheep = new Sheep('Jolly'); +console.log(original.getName()); // Jolly +console.log(original.getCategory()); // Mountain Sheep + +const cloned: Sheep = Object.create(original); +cloned.setName('Dolly'); +console.log(cloned.getName()); // Dolly +console.log(cloned.getCategory()); // Mountain Sheep +``` + +프로토타입 패턴은 상속을 구현하는 쉬운 방법일 뿐만 아니라 성능에서의 이점도 챙길 수 있다. 객체 내의 함수를 정의할 때 복사본이 아닌 참조로 생성되어 모든 자식 객체가 동일한 함수를 가리키게 할 수 있기 때문이다. + +기존 객체와 유사한 객체가 필요하거나 복제에 비해 생성 비용이 많이 드는 경우에 사용한다. + +### 팩토리 패턴 + +> ex. 인사 담당자의 경우, 각 포지션에 대해 한 사람이 모든 면접을 진행하는 것은 불가능하다. 채용 공고에 따라 면접 절차를 결정하고 다른 사람들에게 위임해야 한다. + +```javascript +abstract class HiringManager { + // Factory method + protected abstract makeInterviewer(): Interviewer; + + public takeInterview() { + const interviewer = this.makeInterviewer(); + interviewer.askQuestions(); + } +} + +interface Interviewer { + askQuestions(): void; +} + +class Developer implements Interviewer { + askQuestions() { + console.log('Asking about design patterns!'); + } +} + +class CommunityExecutive implements Interviewer { + askQuestions() { + console.log('Asking about community building'); + } +} + +class DevelopmentManager extends HiringManager { + protected makeInterviewer(): Interviewer { + return new Developer(); + } +} + +class MarketingManager extends HiringManager { + protected makeInterviewer(): Interviewer { + return new CommunityExecutive(); + } +} + +const devManager = new DevelopmentManager(); +devManager.takeInterview(); // 출력: Asking about design patterns! + +const marketingManager = new MarketingManager(); +marketingManager.takeInterview(); // 출력: Asking about community building. +``` + +클래스에 일부 일반적인 처리가 있지만 필수 자식 클래스가 런타임에 동적으로 결정될 때 유용하다. 다른 말로 하면, 클라이언트가 정확히 어떤 자식 클래스가 필요한지 모를 때 사용된다. + +## 참고 + +- [(번역) 우리들을 위한 디자인 패턴](https://soobing.github.io/cs/design-patterns-for-humans/)