본문 바로가기

Software Development/디자인 패턴

[디자인 패턴의 정석] 생성패턴 - 팩토리 패턴 (Factory)

개발자 yeah의 Developer Story - 디자인 패턴

 

오늘은 디자인 패턴에서 생성패턴의 한 종류인 팩토리 패턴을 이야기해보려 합니다.

 

 

팩토리 패턴의 설명에 앞서 생성패턴이란?

  • 큰 규모의 응용 프로그램을 객체지향 개발 방식으로 설계할 때는 수많은 객체가 필요하게 되는데요.
    이때 직접 객체를 생성하고 관계를 설정하면 매우 강력한 결합 관계를 갖게 됩니다.

  • 이때의 관계를 종속 관계라고 하는데요. 이러한 종속 관계객체의 확장과 유지보수를 어렵게 하는 원인이 돼요.
    생성 패턴객체 간 강력한 관계를 느슨한 결합으로 변경하는 기법입니다.

 

팩토리 패턴 생성패턴 중에서도 가장 기본이 되는 패턴이며, 클래스의 객체 생성 처리를 위임합니다.

 

예를 들어 다음 코드를 살펴보겠습니다.

 

/* 마피아 게임에서 사용자를 나타내는 class */
abstract class User {
    String name;    //사용자 이름
    String skill;   //스킬

    User(String name) { this.name = name; }
    
    String getName() { return name; }
    
    String getSkill() { return skill; }
}

 

/* 마피아 게임에서 마피아를 나타내는 class */
public class Mafia extends User {
    Mafia(String name) {
        super(name);
        setSkill();
    }
    
    void setSkill() {
        this.skill = "시민을 죽일수있음";
    }
}

 

/* 마피아 게임에서 경찰을 나타내는 class */
public class Police extends User {
    Police(String name) {
        super(name);
        setSkill();
    }
    
    void setSkill() {
        this.skill = "마피아를 찾을수있음";
    }
}

 

/* 마피아 게임에서 시민을 나타내는 class */
public class Citizen extends User{
    Citizen(String name) {
        super(name);
        setSkill();
    }
    
    void setSkill() {
        this.skill = "투표를 행사할수있음";
    }
}

 

User(사용자)라는 추상 클래스가 있고 이를 상속받는 Mafia(마피아), Police(경찰), Citizen(시민) 클래스가 있습니다.

 

public class FactoryPattern {

    /* 마피아 게임 */
    public static void main(String[] args) {
        Factory factory = new Factory();
        User user1 = new Mafia("성민");
        User user2 = new Police("영성");
        User user3 = new Citizen("승주");
        User user4 = new Citizen("수지");

        System.out.println("이름 :  " + user1.getName() + ",  직업 스킬 : " + user1.getSkill());
        System.out.println("이름 :  " + user2.getName() + ",  직업 스킬 : " + user2.getSkill());
        System.out.println("이름 :  " + user3.getName() + ",  직업 스킬 : " + user3.getSkill());
        System.out.println("이름 :  " + user4.getName() + ",  직업 스킬 : " + user4.getSkill());
    }
}

 

해당 main을 보면 User 클래스에 원하는 직업(Mafia, Police, Citizen)에 따라 new로 생성해 주고 있습니다.

이로써 FactoryPattern 클래스직업(Mafia, Police, Citizen) 클래스 간에 강력한 결합(new로 직접 생성)이 생깁니다.

 

 

그렇다면 해당 코드의 문제점이 무엇일까요?

위처럼 강력한 결합 관계 상태가 되면 클래스 이름 등이 변경될 때 이름을 통해 생성된 코드를 모두 직접 찾아 수정해야 합니다.

강력한 객체의 결합 코드는 향후 유연한 코드 확장을 방해하고 변경과 수정을 어렵게 만듭니다.

 

 

위의 문제점을 해결하기 위해 팩토리 패턴 사용해봅시다!

 

팩토리 패턴 을 적용하기 위해 객체 생성 처리를 위임받는 클래스 Factory 를 정의합니다.

 

/* 객체 생성의 위임을 위한 Factory class */
public class Factory {
    public User create(String name, String job) {
        switch (job) {
            case "마피아":
                return new Mafia(name);
            case "경찰":
                return new Police(name);
            default:    //시민
                return new Citizen(name);
        }
    }
}

 

해당 Factory 클래스의 create 함수에 매개변수사용자 이름원하는 직업을 전달합니다.

 

그다음 직업(Mafia, Police, Citizen) 조건에 따라 클래스를 생성합니다.

 

위와 같이 팩토리 패턴 생성할 객체를 선택할 수 있는 조건 로직이 필수이며 이때 외부의 매개변수값을 받아서 처리합니다.

※외부의 매개변수값은 대부분 문자열을 사용하지만, 안정성을 위해 상수로 정의하여 사용하는 것이 좋습니다.

 

public class FactoryPattern {

    /* 마피아 게임 */
    public static void main(String[] args) {
        Factory factory = new Factory();
        User user1 = factory.create("성민", "마피아");
        User user2 = factory.create("영성", "경찰");
        User user3 = factory.create("성민", "시민");
        User user4 = factory.create("수지", "시민");

        System.out.println("이름 :  " + user1.getName() + ",  스킬 : " + user1.getSkill());
        System.out.println("이름 :  " + user2.getName() + ",  스킬 : " + user2.getSkill());
        System.out.println("이름 :  " + user3.getName() + ",  스킬 : " + user3.getSkill());
        System.out.println("이름 :  " + user4.getName() + ",  스킬 : " + user4.getSkill());
    }
}

 

다음  Factory 클래스 적용한 main을 보시면 new 키워드 없이 객체 생성을 위임하여 처리 된 것을 볼 수 있습니다.

이로써 객체의 생성 처리를 동적으로 위임하므로 향후 클래스가 추가되거나 변경돼도 코드를 쉽게 수정할 수 있습니다.

 

 

 

이렇게 오늘은 디자인 패턴에서 생성패턴의 한 종류인 팩토리 패턴을 이야기해봤는데요.

 

다음 포스팅으로는 해당 팩토리 패턴을 확장한 팩토리 메서드 패턴, 추상 팩토리 패턴을 소개하도록 하겠습니다.

 

감사합니다!