코드스피츠 86 객체지향 자바스크립트 - 3회차 part1 (step 32)

KHW·2021년 3월 26일
1

js-study

목록 보기
19/39
post-custom-banner

Strategy Pattern

전략을 쉽게 바꿀 수 있도록 해주는 디자인 패턴


  1. function 사용
var Strategy = (function() {
  function Strategy() {
    this.strategy = null;
  }
  Strategy.prototype.setStrategy = function(strategy) {
    this.strategy = strategy;
  };
  Strategy.prototype.execute = function() {
    this.strategy.execute();
  };
  return Strategy;
})();

var ShipStrategy = (function() {
  function ShipStrategy() {}
  ShipStrategy.prototype.execute = function() {
    console.log('배로 이탈리아에 갑니다');
  };
  return ShipStrategy;
})();

var LandStrategy = (function() {
  function LandStrategy() {}
  LandStrategy.prototype.execute = function() {
    console.log('육로로 이탈리아에 갑니다');
  };
  return LandStrategy;
})();

var strat = new Strategy();
var ship = new ShipStrategy();
var land = new LandStrategy();
strat.setStrategy(ship);
strat.setStrategy(land); // 전략을 바꿈
strat.execute(); // 어떤 전략이든 설정된 것을 실행
// 육로로 이탈리아에 갑니다.

  1. Class 사용
 const Strategy = class{
        constructor(){
            this.strategy = null;
        }
        setStrategy(strategy){
            this.strategy = strategy;
        }
        execute() {
            this.strategy.execute();
        };
    }

    const ShipStrategy = class{
        constructor(){};
        execute(){
            console.log('배로 이탈리아에 갑니다');
        }
    }

    const LandStrategy = class{
        constructor() {}
        execute() {
        console.log('육로로 이탈리아에 갑니다');
        }
    };

    var strat = new Strategy();
    var ship = new ShipStrategy();
    var land = new LandStrategy();
    strat.setStrategy(ship);
    strat.setStrategy(land); // 전략을 바꿈
    strat.execute(); // 어떤 전략이든 설정된 것을 실행
    // 육로로 이탈리아에 갑니다.

전략을 설정하는 부분 따로, 실행하는 부분 따로라서, 전략을 설정해두면 실행하기 전에 자유롭게 전략을 바꿀 수 있다.


Dependency Injection

효과

Unit Test가 용이해진다.
코드의 재활용성을 높여준다.
객체 간의 의존성(종속성)을 줄이거나 없엘 수 있다.
객체 간의 결합도이 낮추면서 유연한 코드를 작성할 수 있다.


Binder의 수정

기존의 Binder

const Binder = class {
  #items = new Set;

  add(v, _ = type(v, BinderItem)) {
    this.#items.add(v);
  }

  render(viewmodel, _ = type(viewmodel, ViewModel)) {
    this.#items.forEach(item => {
      const vm = type(viewmodel[item.viewmodel], ViewModel), el = item.el;
      Object.entries(vm.styles).forEach(([k, v]) => el.style[k] = v);
      Object.entries(vm.attributes).forEach(([k, v]) => el.setAttribute(k, v));
      Object.entries(vm.properties).forEach(([k, v]) => el[k] = v);
      Object.entries(vm.events).forEach(([k, v]) => el['on' + k] = e => v.call(el, e, viewmodel)); // this 를 el 로 바인딩
    });
  }
};

수정 binder

const Binder = class {
  #item = new Set
  #processors = {}  // category당 한 개의 processor를 사용하게 하기 위함
                    // 자료구조를 선택할 때 심각하게 생각해야 한다.
                    
  add (v, _ = type(v, BinderItem)) { this.#item.add(v) }
  
  // Strategy를 주입 받는다.
  addProcessor (v, _ = type(v, Processor)) { this.#processors[v.category] = v }
  
  // Render에서 주입 받은 Strategy를 사용한다.
  render (viewmodel, _ = type(viewmodel, ViewModel)) {
    const processores = Object.entries(this.#processors)
    this.#item.forEach(item => {
      const vm = type(viewmodel[item.viewmodel], ViewModel), el = item.el
      processores.forEach(([pk, processor]) => {
        Object.entries(vm[pk]).forEach(([k, v]) => {
          processor.process(vm, el, k, v)
        })
      })
    })
  }
}

binder.addProcessor(new class extends Processor {
  _process (vm, el, k, v) { el.style[k] = v }
}('styles'))
binder.addProcessor(new class extends Processor {
  _process (vm, el, k, v) { el.setAttribute(k, v) }
}('attributes'))
binder.addProcessor(new class extends Processor {
  _process (vm, el, k, v) { el[k] = v }
}('properties'))
binder.addProcessor(new class extends Processor {
  _process (vm, el, k, v) { el[`on${k}`] = e => v.call(el, e, vm) }
}('events'))

binder가 프로세서를 주입받는다.


Object.defineProperty()

객체에 직접 새로운 속성을 정의하거나 이미 존재하는 속성을 수정한 후, 그 객체를 반환합니다.

const object1 = {};

Object.defineProperty(object1, 'property1', {
  value: 42,
  writable: false
});

object1.property1 = 77;
// throws an error in strict mode

console.log(object1.property1);
// expected output: 42
const object1 = {};

Object.defineProperty(object1, 'property1', {
  value: 42,
  writable: true
});

object1.property1 = 77;

console.log(object1.property1);
// expected output: 77

출처

DI
코드스피츠
전략패턴

profile
나의 하루를 가능한 기억하고 즐기고 후회하지말자
post-custom-banner

0개의 댓글