본문 바로가기
Language/JavaScript

추상 팩토리 패턴(Abstract Factory Pattern) 예시 - 자바스크립트(JavaScript ES5 /ES6)

by DevPark 2024. 4. 10.

 

자바스크립트로 구현한 추상팩토리 디자인패턴을 번역하여 소개합니다. 

상황과 그에 대한 솔루션을 객체지향적인 디자인패턴과 다르게 자바스크립트스럽게(?) 구현된 예제입니다.

객체지향적으로 설계한 코드도 확인할 수 있습니다.  

자세한 내용은 아래 원문을 참고해주세요.

 

JavaScript-Design-Patterns/GoF/idiomatic/Creational/AbstractFactory at master · Badacadabra/JavaScript-Design-Patterns

:paperclip: ES5 + ES6 + CoffeeScript + TypeScript design patterns with some theory, real-world examples and UML diagrams - Badacadabra/JavaScript-Design-Patterns

github.com


개요 (Synopsis)

저는 시스템 관리자로서 각 직원이 운영 체제를 선택할 수 있는 회사에서 일합니다. 

그래서 저는 종종 GNU/Linux, Mac OS 또는 Windows 기반의 다양한 운영 체제를 설치하고 실행해야 합니다.

Linux

문제 (Problem)

운영 체제에는 여러 종류가 있으며 각 운영체제에는 여러 버전들과 파생된 운영 체제가 있습니다.

맥이나 윈도우즈 같은 경우는 여러 버전이 존재하고 리눅스의 경우에는 수많은 배포판이 존재합니다.  

모든 인스턴스화 로직을 클라이언트 코드에서 처리하려고 하면 대부분의 경우 혼란스러울 것입니다.

 

시스템 관리자로서, 특정 종류의 특정 운영 체제 인스턴스를 가져오는 방법만 알고 싶습니다.

Debian, Mac OS X 또는 Windows XP가 어떻게 프로그래밍되어 일부 컴퓨터에서 사용 가능하게 되었는지 알 필요가 없습니다.

해결 (Solution)

여기서 추상 팩토리 패턴(Abstract Factory)은 훌륭한 해결책입니다. 

이것은 Factory 패턴의 슈퍼셋으로 간주할 수 있지만, 수행해야 할 작업이 상당히 많습니다. 

실제로 각 운영 체제 종류에 대한 팩토리 함수가 필요하며, 물론 해당 모듈의 진입점이 될 팩토리의 팩토리도 필요합니다.

 

 


ES5 버전 

Client  코드 (client.js)

'use strict';

var getOSFactory = require('./API/factories');

// ==============================
// CLIENT CODE 
// ==============================

// 추상 팩토리로부터 구체적인 팩토리를 얻을 수 있습니다.
var linuxFactory = getOSFactory('LINUX'),
    macFactory = getOSFactory('Mac'),
    windowsFactory = getOSFactory('windows');

// 그런 다음에 우리는 이러한 구체적인 팩토리로부터 실제 객체를 얻을 수 있습니다.
var debian = linuxFactory('DEBIAN'),
    osx = macFactory('osX'),
    xp = windowsFactory('xp');

console.log(debian.bootLinux()); // Debian is booting...
console.log(osx.bootMac()); // Mac OS X is booting...
console.log(xp.bootWindows()); // Windows XP is booting...

 

API 코드 (factories.js)

'use strict';

// ==============================
// GNU/LINUX FACTORY
// ==============================

var getLinuxDistro = function (name) {
    name = name.toLowerCase();

    var linuxDistro = {
        bootLinux: function () {
            return this.name + " is booting...";
        }
    };

    switch (name) {
        case "debian":
            linuxDistro.name = "Debian";
            return linuxDistro;
        case "redhat":
            linuxDistro.name = "RedHat";
            return linuxDistro;
        default:
            throw {
                type: "Not found",
                message: "The Linux distribution you are looking for has not been found"
            }
    }
};

// ==============================
// MAC FACTORY
// ==============================

var getMacRelease = function (name) {
    name = name.toLowerCase();

    var macRelease = {
        bootMac: function () {
            return this.name + " is booting...";
        }
    };

    switch (name) {
        case "os9":
            macRelease.name = "Mac OS 9";
            return macRelease;
        case "osx":
            macRelease.name = "Mac OS X";
            return macRelease;
        default:
            throw {
                type: "Not found",
                message: "The Mac release you are looking for has not been found"
            }
    }
};

// ==============================
// WINDOWS FACTORY
// ==============================

var getWindowsVersion = function (name) {
    name = name.toLowerCase();

    var windowsVersion = {
        bootWindows: function () {
            return this.name + " is booting...";
        }
    };

    switch (name) {
        case "xp":
            windowsVersion.name = "Windows XP";
            return windowsVersion;
        case "vista":
            windowsVersion.name = "Windows Vista";
            return windowsVersion;
        default:
            throw {
                type: "Not found",
                message: "The Windows version you are looking for has not been found"
            }
    }
};

// ==============================
// FACTORY OF FACTORIES 
// ==============================

module.exports = function (name) {
    name = name.toLowerCase();
    switch (name) {
        case "linux":
            return getLinuxDistro;
        case "mac":
            return getMacRelease;
        case "windows":
            return getWindowsVersion;
        default:
            throw {
                type: "Not found",
                message: "The factory you are looking for has not been found"
            }
    }
};

 


ES6 버전 

Client  코드 (client.js)

import getOSFactory from './API/factories';

// ==============================
// CLIENT CODE 
// ==============================

// 추상 팩토리에서 구체적인 팩토리를 얻을 수 있습니다.
let linuxFactory = getOSFactory('LINUX'),
    macFactory = getOSFactory('Mac'),
    windowsFactory = getOSFactory('windows');

// 그런 다음 이러한 구체적인 팩토리에서 실제 객체를 얻을 수 있습니다.
let debian = linuxFactory('DEBIAN'),
    osx = macFactory('osX'),
    xp = windowsFactory('xp');

console.log(debian.bootLinux()); // Debian is booting...
console.log(osx.bootMac()); // Mac OS X is booting...
console.log(xp.bootWindows()); // Windows XP is booting...

 

API 코드 (factories.js)

// ==============================
// GNU/LINUX FACTORY
// ==============================

const getLinuxDistro = name => {
    name = name.toLowerCase();

    const linuxDistro = {
        bootLinux() {
            return `${this.name} is booting...`;
        }
    };

    switch (name) {
        case "debian":
            linuxDistro.name = "Debian";
            return linuxDistro;
        case "redhat":
            linuxDistro.name = "RedHat";
            return linuxDistro;
        default:
            throw {
                type: "Not found",
                message: "The Linux distribution you are looking for has not been found"
            }
    }
};

// ==============================
// MAC FACTORY
// ==============================

const getMacRelease = name => {
    name = name.toLowerCase();

    const macRelease = {
        bootMac() {
            return `${this.name} is booting...`;
        }
    };

    switch (name) {
        case "os9":
            macRelease.name = "Mac OS 9";
            return macRelease;
        case "osx":
            macRelease.name = "Mac OS X";
            return macRelease;
        default:
            throw {
                type: "Not found",
                message: "The Mac release you are looking for has not been found"
            }
    }
};

// ==============================
// WINDOWS FACTORY
// ==============================

const getWindowsVersion = name => {
    name = name.toLowerCase();

    const windowsVersion = {
        bootWindows() {
            return `${this.name} is booting...`;
        }
    };

    switch (name) {
        case "xp":
            windowsVersion.name = "Windows XP";
            return windowsVersion;
        case "vista":
            windowsVersion.name = "Windows Vista";
            return windowsVersion;
        default:
            throw {
                type: "Not found",
                message: "The Windows version you are looking for has not been found"
            }
    }
};

// ==============================
// FACTORY OF FACTORIES 
// ==============================

export default name => {
    name = name.toLowerCase();
    switch (name) {
        case "linux":
            return getLinuxDistro;
        case "mac":
            return getMacRelease;
        case "windows":
            return getWindowsVersion;
        default:
            throw {
                type: "Not found",
                message: "The factory you are looking for has not been found"
            }
    }
};

 

 

반응형

댓글