팩토리는 공장이란 뜻을 내포하고 있다.
따라서 팩토리 메서드 패턴도 무언가를 위한 공장이라 봐도 무방하다.
일반적으로 팩토리 메서드 패턴을 객체를 만들어내는 부분을 서브 클래스에 위임하는 패턴이라고 말할 수 있다.
Factory Method Pattern
- 객체를 생성하기 위해 인터페이스를 정의하지만, 어떤 클래스의 인스턴스를 생성할지에 대한 결정은 서브 클래스가 내린다.
- 객체 생성을 캡슐화하는 패턴이다.
아래 예시를 보면 쉽게 파악할 수 있다.
로봇이 있고, 이를 슈퍼로봇과 파워로봇으로 구체화할 수 있다.
로봇팩토리를 통해 로봇을 생산할 수 있다.
우선 간략한 구조는 이러하다.
Robot(abstract class)
┗ SuperRobot
┗ PowerRobot
RobotFactory(abstract class)
┗ SuperRobotFactory
┗ ModifiedSuperRobotFactory
로봇클래스를 추상클래스로 만들었다.
public abstract class Robot {
public abstract String getName();
}
이를 구체화한 슈퍼로봇과 파워로봇이다. 각각의 이름을 반환하는 메서드를 재정의하였다.
public class SuperRobot extends Robot {
@Override
public String getName() {
return "SuperRobot";
}
}
public class PowerRobot extends Robot {
@Override
public String getName() {
return "PowerRobot";
}
}
다음은 팩토리 클래스이다.
public abstract class RobotFactory {
public abstract Robot createRobot(String name);
}
매개변수로 들어온 이름에 따라 알맞은 로봇을 생성해서 반환해 준다.
public class SuperRobotFactory extends RobotFactory {
@Override
public Robot createRobot(String name) {
if (name.equalsIgnoreCase("Super")) {
return new SuperRobot();
}
if (name.equalsIgnoreCase("power")) {
return new PowerRobot();
}
return null;
}
}
슈퍼로봇팩토리클래스와 비슷하지만 아래 클래스는 String인자를 받아서 직접 인스턴스를 만들어낸다.
public class ModifiedSuperRobotFactory extends RobotFactory {
@Override
public Robot createRobot(String name) {
try {
Class<?> robot = Class.forName(name);
return (Robot) robot.getDeclaredConstructor().newInstance();
} catch (Exception e) {
return null;
}
}
}
이를 활용하여 테스트를 진행하면 통과하게 된다.
package pattern;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class RobotFactoryTest {
@Test
public void superRobotFactoryTest() {
RobotFactory robotFactory = new SuperRobotFactory();
Robot robot1 = robotFactory.createRobot("super");
Robot robot2 = robotFactory.createRobot("power");
Assertions.assertEquals(robot1.getClass(), SuperRobot.class);
Assertions.assertEquals(robot2.getClass(), PowerRobot.class);
}
@Test
public void modifiedSuperRobotFactoryTest() {
RobotFactory robotFactory = new ModifiedSuperRobotFactory();
Robot robot1 = robotFactory.createRobot("pattern.SuperRobot");
Robot robot2 = robotFactory.createRobot("pattern.PowerRobot");
Assertions.assertEquals(robot1.getClass(), SuperRobot.class);
Assertions.assertEquals(robot2.getClass(), PowerRobot.class);
}
}
로봇을 생성할 때 new 키워드 없이 객체 생성을 팩토리 클래스에 위임한 것을 볼 수 있다.
또한 메인 프로그램은 어떤 객체가 생성되었는지 신경 쓰지 않고, 단지 반환된 객체를 사용만 하면 된다.
또한 팩토리가 추가된다 하더라도 메인 프로그램에서 변경할 코드는 최소화된다.
정리
팩토리 메서드 패턴을 사용하는 이유는 클래스 간의 결합도를 낮추기 위함이다.
결합도는 클래스의 변경점이 생겼을 때 얼마나 다른 클래스에도 영향을 주는가 이다.
팩토리 메서드 패턴을 사용하는 경우 직접 객체를 생성해 사용하는 것을 방지하고 서브 클래스에 위임함으로써 보다
효율적으로 코드를 제어하고 의존성을 제거할 수 있다. 결과적으로 결합도 또한 낮출 수 있다.
'CS' 카테고리의 다른 글
옵저버 패턴(Observer Parttern) (0) | 2023.05.11 |
---|---|
전략 패턴(Strategy Pattern) (0) | 2023.05.10 |
싱글톤 패턴(Singleton Pattern) (0) | 2023.04.27 |
컴퓨터 시스템의 구성 (0) | 2023.04.16 |
데이터베이스 언어 SQL (0) | 2023.04.15 |