본문 바로가기
Javascript/Node.js

Template Pattern - 행위 디자인 패턴

by v8rus 2022. 2. 9.

템플릿 (Template)

전략패턴과 공통점이 많음
템플릿 패턴 : 컴포넌트의 스켈레톤(공통부분을 나타냄) 을 구현하는 추상 클래스를 정의
  다만 일부 단계는 정의되지 않은 상태로 존재
  하위 클래스는 템플릿 함수라고하는 누락된 함수부분을 구현하여 컴포넌트의 빈 부분을 채움

목적: 모든 컴포넌트의 모든 변형 집합을 정의할 수 있도록 하는것

 

JS 는 추상 클래스를 정의하는 공식적인 방법이없음.

함수를 정의하지 않은 상태로 두거나 항상 예외를 발생시키는 함수에 할당하여 함수를 구현해야 함


템플릿과 전략 패턴은 매우 유사함, 중요한 차이점은 구조와 구현에 있음
둘다 공통 부분을 재사용하면서 구성 요소의 가변 부분을 변경할 수있음
전략 : 실행 시 동적으로 수행
템플릿 : 구체적인 클래스가 정의되는 순간, 전체 컴포넌트의 동작이 결정됨
  => 컴포넌트의 사전에 패키징된 변형을 생성하려는 상황에 더 적합?? 뭔소리야

 

 

1. 환경 설정 관리 템플릿

전략과 템플릿 차이를 잘 이해하기 위해 Config 객체 다시 씀
이번엔 템플릿 패턴을 사용, 일련의 환경설정 속성 로드, 저장

 // ConfigTemplate.JS
import {promises as fsPromises} from 'fs';
import objectPath from 'objectPath';

export class ConfigTemplate {
  async load (file) {
    console.log(`Deserialize from ${file}`);
    this.data = this._deserialize(
      await fsPromises.readFile(file, 'utf-8');
    )

    async save (file) {
      console.log(`Serializing to ${file}`);
      await fsPromises.wrtieFile(file, this._serialize(this.data));
    }

    get (path) {
      return objectPathget(this.data, path);
    }

    set(path, value) {
      return objectPath.set(this.data, path, value);
    }

    _serialize() {
      throw new Error(`_serialize() must be implemented`);
    }
    _deserialize () {
      throw new Error(`_deserialize() must be implemented`);
    }
  }
}

로직의 공통부분(속성 설정)을 구현
serialize, deserialize의 함수 구현은 열어 둠
  => 특정 환경 설정 형식을 지원하는 구체적인 Config 클래스를 생성할 수 있도록 하는 템플릿 함수

 

! 밑줄 '_' 은 보호된 함수에 플래그를 지정하는 간편한 방법으로 내부 전용임을 나타냄
! JS는 추상으로 함수 선언 불가 => 단순한 모형(stubs) 로 정의하여 호출하면 (구체적 하위 클래스에서 재정의 되지 않은경우) 오류 발생시킴

 


JsonConfig 클래스는 ConfigTemplate 를 확장, _de/serialize() 함수 구체적으로 구현

import { ConfigTemplate } from './ConfigTemplate.js';

export class JsonConfig extends configTemplate {
  _deserialize() {
    return JSON.parse(data);
  };
  _serialize(data) {
    return JSON.stringify(daya, null, ' ');
  }
}

 

INI 확장자 까지 확장해봅시다.

import { ConfigTemplate } from './ConfigTemplate';
import ini from 'ini';

export classs IniConfig extneds ConfigTemplate {
  _deserialize () {
    return ini.parse(data);
  };
  _serialize() {
    return ini.stringify(data);
  }
}

 

환경설정 관리자 클래스 사용, 일반 환경설정 데이터 로드 및 저장

import { JsonConfig } from './jsonConfig.js';
improt { IniConfig } from './iniConfig.js';

async function main() {
  const jsonConfig = new JsonConfig();
  await jsonCofig.load('samples/conf.json');
  jsonCofig.set('nodejs', 'designpattern');
  await jsonConfig.save('samples/conf_mod.json');

  const iniConfig = new IniConfig();
  await iniConfig.load('samples/conf.ini');
  iniConfig.set('nodejs', 'design patern');
  await iniConfig.save('samples/conf_mod.ini');
}

main();

전략 패턴과의 차이점에 주의해야 함, 환경 설정 데이터를 형식화 하고 구문을 분석하는 로직은 런타임에 결정되지 않고 클래스 자체에 포함되어 있음
=> 그럼 로드하는 파일이 더 증가하지?? 추가적인 옵션을 가지고 있으니까

템플릿 패턴을 사용해 부모 템플릿 클래스에서 상속된 로직과 인터페이스들을 재사용하고 몇가지 추상 함수의 구현만을 제공함으로 최소한의 작업만으로도 새로운 환경설정 관리자를 만들 수 있음

 

 

Summary

스트림 클래스르 확장할때 비슷하게 사용핬음
새로운 사용자 정의 스트림을 생성하려면 특정 추상 스트림클래스에서 상속을 받아 템플릿 함수들에 대한 구현을 제공해야 함

댓글