1. 팩토리 메소드 패턴이란

GoF의 디자인 패턴에서 제시한 디자인 패턴 중 생성 패턴에 속한다. 해당 서적에서는 팩토리 메소드 패턴을 이렇게 정의하고 있다.

객체를 생성하기 위한 인터페이스를 정의하고,
어떤 클래스의 인스턴스를 생성할지에 대한 처리는 서브클래스가 결정하는 디자인 패턴

요약해서 말하자면, 객체 생성을 대신 수행해주는 일종의 팩토리가 존재하는 것이다. 이때 객체를 생성하는 메소드를 팩토리 메소드라고 하며, 이를 구현 팩토리 객체에서 Override하여 원하는 객체를 생성하게 된다. 클라이언트에서 직접 객체를 생성하는 것이 아니라, 간접적으로 객체를 생성한 뒤 반환해주는 방식이다.

즉, 해당 디자인 패턴은 상위 클래스에 알려지지 않은 구체 클래스를 생성하는 패턴이며, 하위 클래스가 직접 어떤 객체 인스턴스를 생성할지 결정하게 된다. 이를 UML 형태로 나타내면 아래의 그림과 같다.

출처 : 위키피디아

이때 Creator의 factoryMethod()는 추상 메소드이며, 이를 ConcreteCreator에서 Override하여 구현 메소드를 작성한다. 결국 실질적으로는 ConcreteCreator를 통해서 Client에게 Product를 생성하여 전달하게 된다.

2. 팩토리 메소드 패턴의 사용

팩토리 메소드 패턴을 사용하는 주된 이유는 클래스의 생성과 사용의 처리 로직을 분리하여 결합도를 낮추기 위해서이다. 팩토리 메소드 패턴을 사용하여 직접 객체를 생성해 사용하는 것을 방지하고, 서브클래스에 생성 로직을 위임함으로써 보다 효율적으로 코드를 제어할 수 있고, 의존성을 제거해 주는 역할을 한다.

또한, 객체 생성을 캡슐화하고 한 곳(팩토리 클래스)에서 관리하기 때문에 수정에는 닫혀 있고, 객체의 자료형이 하위클래스에 의하여 결정된다는 점 때문에 확장이 용이하다는 장점이 있다. 이는 객체지향의 SOLID 원칙 중 OCP에 해당한다.

3. 팩토리 메소드 패턴 예제 코드(by. Java)

Computer 추상 클래스

abstract class Computer {
    public void on() { // 컴퓨터 전원버튼으로 켜기 }
    public void off() { // 컴퓨터 전원버튼으로 끄기 }
    
    abstract void compose(); // 컴퓨터 조립하는 방법
    abstract void use(); // 컴퓨터 사용하는 방법
}

Computer는 on, off, compose, use라는 공통적인 메소드를 갖는 인터페이스이다. 컴퓨터라는 종류로 추상화되어 있는 상태이다. 이때, on과 off 메소드의 경우 어느 컴퓨터든 전원버튼을 이용하여 켜고 끈다는 동일한 행위를 수행하기 때문에 구체 클래스에서의 구현을 줄이기 위해 미리 구현해 두었다.

Computer 구체 클래스

public class Macbook extends Computer {
    @Override
    void compose() { // 맥북이 조립되어 나오는 과정 }
    
    @Override
    void use() { // 트랙패드로 사용하기 }
}

public class Galaxy extends Computer {
    @Override
    void compose() { // 갤럭시북이 조립되어 나오는 과정 }
    
    @Override
    void use() { // 360도로 꺾어서 사용하기 }
}

public class Asus extends Computer {
    @Override
    void compose() { // Asus 노트북이 조립되어 나오는 과정 }
    
    @Override
    void use() { // 평범하게 마우스로 사용하기 }
}

public class Lenova extends Computer {
    @Override
    void compose() { // Lenova 노트북이 조립되어 나오는 과정 }
    
    @Override
    void use() { // 빨콩으로 사용하기 }
}

Computer라는 추상화된 인터페이스를 활용하여 구현한 구체 클래스이다. 각 클래스마다 조립되어 나오는 과정과 사용 방식을 구현해 둔 상태이다.

ComputerFactory 추상 클래스

abstract class ComputerFactory {
    public Computer orderComputer(String type){
        Computer computer = createComputer(String); // Factory Method
        computer.compose();
        computer.on();
        computer.off();
        return computer;
    }
    
    abstract Computer createComputer(String type); // Factory Method
}

ComputerFactory는 위의 그림에서 Creator 역할을 한다. 이때 createComputer 부분이 팩토리 메소드가 되고, 이 부분을 구체 클래스에서 실질적으로 구현하여 어떤 객체 인스턴스를 반환할지 결정하게 된다. 그리고 추상 객체에서는 orderComputer 메소드 내부에서 팩토리 메소드를 활용하여 Computer를 생성하고, 기능들을 사용하고 있다.

ComputerFactory 구체 클래스

class ComputerFactoryImpl extends ComputerFactory {
    @Override
    Computer createComputer(String type) {
        if ("Macbook".equals(type)) {
            return new Macbook();
        } else if ("Galaxy".equals(type)) {
            return new Galaxy();
        } else if ("Asus".equals(type)) {
        	return new Asus();
        } else if ("Lenova".equals(type)) {
        	return new Lenova();
        }
        return null;
    }
}

위 두 클래스는 ComputerFactory를 구현한 구체 클래스이다. 객체의 종류가 추가되는 경우, 구체 클래스에 추가해줌으로써 새로운 객체를 반환할 수 있다. 기능의 추가가 필요한 경우 해당 구체 클래스만 변경하고, 추상 클래스는 변경하지 않아도 된다.

팩토리 메소드에 String 값을 인자로 받아 리턴되는 객체의 종류를 변화시킨다. 해당 구체 클래스를 실제로 클라이언트에서 사용함으로써 클라이언트 단에서 리턴되는 객체의 종류를 제어할 수 있다.

클라이언트 코드

public class FactoryPatternTest {
    public static void main(String[] args) {
        ComputerFactory computerFactory = new ComputerFactoryImpl();
        
        Computer macbook = computerFactory.orderComputer("Macbook");
        Computer galaxy = computerFactory.orderComputer("Galaxy");
        Computer asus = computerFactory.orderComputer("Asus");
        Computer lenova = computerFactory.orderComputer("Lenova");
    }
}

위와 같은 형태로 팩토리를 통해 생성되는 객체들의 종류를 제어할 수 있다.

반응형

소프트웨어 개발을 위한 여러 디자인 패턴들 중, 웹 서비스에 자주 사용되는 패턴으로 MVC 디자인 패턴이 있다. Spring MVC, Django 등에서 활용되고 있는 패턴이다.

MVC란 Model, View, Controller의 앞글자를 따서 MVC 패턴이라고 부르며, 애플리케이션을 세 가지의 역할로 구분하는 개발 방법론이다. 그림처럼, 사용자는 Controller만 조작하고, Controller는 Model을 통하여 데이터를 가져오게 되며, 그 정보를 바탕으로 시각적인 표현을 담당하는 View를 통해 사용자에게 전달하게 된다.

MVC (출처 : 생활코딩)

간단히 말해서, 사용자는 Controller를 통해 입력하고, View를 통해 출력을 받는다고 볼 수 있다. 일종의 추상화 개념이라고 볼 수 있다. 위의 그림의 경우, Controller와 View의 연관 관계는 표현되어 있지 않는데, 실제로는 Controller에서 View에도 영향을 줄 수 있고, Model이 Controller에도 정보를 전달할 수 있다..

각각의 구성 요소들은 각자의 역할을 수행해야 하며, 각각의 구성 요소가 다른 요소들에게 영향을 미치지 않고 각자의 역할에 충실해야 한다는 것이 MVC 패턴의 핵심이다.

Controller는 Model에 명령을 보냄으로써 Model의 상태를 변경할 수 있어야 한다(Manipulate). 또한, Controller는 관련된 View에도 명령을 보냄으로써, Model의 표시 방법을 바꿀 수 있어야 한다. 

Model은 Model의 상태에 변화가 있을 때, Controller와 View에 해당 내용을 전달한다. 이와 같은 행위를 통해, View는 최신의 결과를 보여주고, Controller는 Model의 변화에 따라 명령을 추가하거나, 제거하거나, 수정할 수도 있다. 특정 MVC 구현에서는 Model에서 전달하는 것이 아니라, View나 Controller가 직접 Model의 상태를 읽어 오는 경우도 있다.

View는 사용자가 볼 결과물을 생성하기 위해 Model로부터 정보를 얻어 온다.

Django에서는 Model, View, Controller를 각각 Model, Template, View로 사용하고 있다.

일반적으로 Model의 경우 클래스 형태로 표현되며, 이 클래스는 하나의 데이터베이스 테이블이라고 볼 수 있다. Django의 경우 ORM(Object Relational Mapping)이라는 데이터베이스 기능을 지원하기 때문에, 파이썬 코드를 통해서 DB Handling이 가능하다.

Template의 경우 HTML 형태로 구현되며, View에게 받은 데이터를 동적으로 적용한다. 이때 Django의 경우, 자체적인 Django Template 문법을 지원하며, 이 문법을 통해 동적으로 적용이 가능하다.

View의 경우, MVC 패턴에서의 컨트롤러에 대응된다. 요청에 따라, 적절한 로직을 수행하고, 결과를 Template에게 전달하는 역할을 한다.

 

참고자료

반응형

+ Recent posts