본문 바로가기

상속(extends) 패턴 & 전략(strategy) 패턴 본문

개발/JavaScript

상속(extends) 패턴 & 전략(strategy) 패턴

자전하는명왕성 2023. 7. 13. 13:23

자바스크립트 내에서 상속 패턴과 전략 패턴은 모두 객체 지향 프로그래밍(OOP)를 지원하는 패턴이다.

둘다 코드의 재사용성을 높이며, 유지보수성을 향상시킨다는 장점이 있다.

 

두 패턴의 차이점에 대해 간단히 얘기하면, 

상속 패턴의 경우, 부모 클래스로부터 다른 클래스가 상속받아 부모 클래스의 메서드나 프로퍼티를 정적으로 재사용하는 패턴이며,

전략 패턴의 경우, 동일한 문제를 해결하기 위해 다양한 알고리즘을 가진 객체들을 정의하고 이를 동적으로 교환하여 사용하는 패턴이다.

 

상속 패턴 (extends)

상속 패턴의 경우, 부모 클래스(기존 클래스)를 상속해 새로운 클래스를 생성하면 상속받은 부모 클래스의 속성과 메서드를 사용할 수 있다고 위에서 언급했다.

이때, 자식 클래스에서 부모 클래스의 메소드를 재정의 할 수 있으나, 자식 클래스의 메소드에서 부모 클래스의 메소드를 직접 호출할 수는 없다.

다음 예시를 들어 설명한다. (상속의 예를 들기 위해, 부모 클래스는 "Animal", 자식 클래스는 "Dog"으로 설정)

class Animal {
  constructor(name) {
    this.name = name
  }

  speak() {
    console.log(`${this.name} 말한다.`)
  }
}

class Dog extends Animal {
  speak() {
      console.log(`${this.name} 멍멍`)
  }
}

let poodle = new Dog('poodle')
poodle.speak() // 'poodle 멍멍'

위 코드는 자식 클래스(Dog)가 부모 클래스(Animal)을 상속한 모습이다.

이때, 자식 클래스(Dog)은 부모 클래스에서 사용한 메서드인 speak를 재정의하였는데,

이를 통해 클래스 Dog로 생성된 변수 poodle이 speak를 사용한 경우

Dog에서 재정의된 메서드가 적용되는 것을 확인할 수 있다.

 

하지만, 다음처럼 부모 클래스의 메소드를 직접 호출할 수는 없다.

다만, super 메서드를 활용하여 부모 클래스의 메서드를 호출하는 것은 가능하다.

class Dog extends Animal {
  speak() {
      console.log(`${this.name} 멍멍`)
      super.speak(); // 가능
      Animal.speak(); // 불가능
  }
}

Animal.speak()의 경우, TypeError 가 발생하는 것을 확인할 수 있다.

 

전략 패턴 (strategy)

전략 패턴은 알고리즘이 독립적으로 변하게 하는 것을 목표로, 알고리즘을 캡슐화하고 구조화한다.

예시를 들기 위해 자식을 Dog과 Cat으로 둔다.

class Animal {
  constructor(name) {
    this.name = name
  }
  speak() {
    this.name.speak()
  }
}

class Dog {
  constructor(name) {
    this.name = name
  }

  speak() {
    console.log(`${this.name} 멍멍`)
  }
}

class Cat {
  constructor(name) {
    this.name = name
  }

  speak() {
    console.log(`${this.name} 야옹`)
  }
}

const poodle = new Animal(new Dog("poodle"))
poodle.speak() // poodle 멍멍

const cheese = new Animal(new Cat("cheese"))
cheese.speak() // cheese 야옹

 

그리고, 다음과 같이 함수를 인자로 전달하여, 동적으로 사용할 수도 있다.

class Animal {
  constructor(name,sound) {
    this.name = name
    this.sound = sound
  }
  
  speak() {
    this.sound(this.name)
  }
}

const dogSound = (name) => {
  console.log(`${name} 멍멍`)
}

const catSound = (name) => {
  console.log(`${name} 야옹`)
}

const any = new Animal("poodle",dogSound)
any.speak() // 'poodle 멍멍'

any.name = "cheese" // 동적 수정
any.sound = catSound // 'cheese 야옹'

any.speak()
Comments