Skip to content

Commit

Permalink
7.14장까지
Browse files Browse the repository at this point in the history
  • Loading branch information
hyesungoh committed Nov 4, 2024
1 parent 43440d7 commit d6f2615
Showing 1 changed file with 206 additions and 0 deletions.
206 changes: 206 additions & 0 deletions 챕터_7/오혜성.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,209 @@ const cat = animalFactory.createAnimal({type: 'cat', name: 'Whiskers'});
### 추상 팩토리 패턴

- 같은 목표를 가진 각각의 팩토리들을 하나의 그룹으로 캡슐화하는 패턴

## 구조 패턴

상속의 개념을 통해 인터페이스와 객체를 구성하여 새로운 기능을 추가할 수 있는 것처럼 이것들의 구성을 다룸

- 퍼사드 패턴
- 믹스인 패턴
- 데코레이터 패턴
- 플라이웨이트 패턴

## 퍼사드 패턴

- 실제 모습을 숨기고 꾸며낸 겉모습만을 세상에 드러내는 것
> 건물의 정면에 있는 외벽을 의미한다네요
- 퍼사드는 jQuery같은 라이브러리에서 흔히 볼 수 있는 구조 패턴
- 밖으로 드러남과 동시에 복잡한 구현은 보이지 않게 숨긴다는 것
> 이걸 추상화라고 이해하고 있긴 한데, 살짝 다를려나?
```ts
const addMyEvent = (element, event, callback) => {
if (element.addEventListener) {
element.addEventListener(event, callback, false);
} else if (element.attachEvent) {
element.attachEvent('on' + event, callback);
} else {
element['on' + event] = callback;
}
}
```

## 믹스인 패턴

- 서브클래스가 쉽게 상속받아 기능을 재사용할 수 있도록 하는 클래스랍디다

## 서브클래싱

- 대충 클래스 상속에 대한 설명

## 믹스인

- 자바스크립트의 클래스는 부모 클래스를 하나만 가질 수 있지만 여러 클래스의 기능을 섞는 것으로 확장할 수 있음
- 표현식이 아니라 문으로 사용할 수도 있음

```js
const MyMixin = (superclass) => class extends superclass {
sayHi() {
console.log('hi');
}
}

class Person {
sayBye() {
console.log('bye');
}
}

const MyPerson = MyMixin(Person);
const person = new MyPerson();
person.sayHi();
person.sayBye();
```

- 함수의 중복을 줄이고 재사용성은 높일 수 있음
- 하지만 클래스나 객체의 프로토타입에 기능을 주입하는 것을 나쁜 방법이라고 여기기도 함
- 출처에 대한 불확실성을 초래하기 때문

- 리액트에서도 ES6 클래스의 도입 이전에는 컴포넌트에 기능을 추가하기 위해 믹스인을 사용하곤 했음
- 그러나 유지보수와 재사용을 복잡하게 만든다는 이유로 반대

> https://ko.legacy.reactjs.org/docs/react-without-es6.html#mixins
> 근데 문서에서는 그냥 쓰지않는 것을 추천한다고 하네요
## 데코레이터 패턴

- 기존 클래스에 동적으로 기능을 추가하기 위해 사용
- 서브클래스를 필요에 따라 만든다면 넘모 많이 만들어야해 실용적이지 않음

```js
class MacBook {
constructor() {
this.cost = 100;
this.screenSize = 13;
}

getCost() {
return this.cost;
}

getScreenSize() {
return this.screenSize;
}
}

class Memory extends MacBook {
constructor(macbook) {
super(macbook);
this.cost = macbook.cost + 1;
}
}

class Engraving extends MacBook {
constructor(macbook) {
super(macbook);
this.cost = macbook.cost + 2;
}
}

let myMacBook = new MacBook();
myMacBook = new Memory(myMacBook);
myMacBook = new Engraving(myMacBook);

console.log(myMacBook.getCost());
// 103
console.log(myMacBook.getScreenSize());
// 13
```

### 의사 클래스 데코레이터

- 인터페이스를 이용한 형태로만 이해됨

### 추상 데코레이터

- 이것도 그냥 인터페이스를 이용한 느낌 정도로만 이해됨

> 그래서 준비한 타입스크립트로 작성한 추상 데코레이터 패턴
```tsx
class MacBook {
// protected ??
// public = 어디서나 접근 가능
// private = 이 클래스 내부에서만 접근 가능
// protected = 이 클래스와 상속받은 클래스에서만 접근 가능
protected cost: number;
protected screenSize: number;

constructor() {
this.cost = 100;
this.screenSize = 13;
}

getCost(): number {
return this.cost;
}

getScreenSize(): number {
return this.screenSize;
}
}

// 데코레이터들이 구현해야 할 인터페이스 (헝가리안 표기법 ㅈㅅ)
interface IMacBook {
getCost(): number;
getScreenSize(): number;
}

// 추상 데코레이터 클래스
abstract class MacBookDecorator implements IMacBook {
protected macbook: IMacBook;

constructor(macbook: IMacBook) {
this.macbook = macbook;
}

getCost(): number {
return this.macbook.getCost();
}

getScreenSize(): number {
return this.macbook.getScreenSize();
}
}

// 구체적인 데코레이터 클래스들
class Memory extends MacBookDecorator {
getCost(): number {
return this.macbook.getCost() + 100; // 메모리 업그레이드 비용 추가
}
}

// abstract class??
// 추상 클래스라, 직접 인스턴스화 불가능 (new MackBookDecorator)
// 추상 메서드를 포함할 수 있음 (구현부가 없는 메서드)
// 상속받는 클래스에서 추상 메서드를 반드시 구현해야 함
//
// 사용하는 이유
// 1. 공통 기능 구현: 여러 클래스가 공유하는 기본 코드를 구현 (코드 재사용)
// 2. 표준화: 파생되는 클래스들이 반드시 구현하도록 강제
abstract class Shape {
abstract getArea(): number; // 모든 도형은 면적을 계산해야 함
}

class Circle extends Shape {
constructor(public radius: number) {
super();
}

getArea(): number {
return Math.PI * this.radius ** 2;
}
}
```



0 comments on commit d6f2615

Please sign in to comment.