팩토리는 new로 간주되는 다른 메소드 호출에 대해 다른 객체를 반환하는 객체.
문제에서 food 인터페이스가 제공된다. 이를 구현하는 두개의 클래스 Pizza와 Cake는 getType() 메소드를 포함한다.
메인 함수에서 FoodFactory클래스의 인스턴스를 생성한다.
이 클래스에는 파라미터에 따라 Pizza 또는 Cake의 새 인스턴스를 반환하는
getFood(String)메소드가 포함된다.
핵심은 클래스의 인스턴스를 만드는 것을 서브클래스에서 결정하도록 한다는 것이다. 객체를 만들어내는 부분(new 키워드를 호출하는 부분)을 서브클래스에 위임한다.
인터페이스를 미리 정의하지만, 인스턴스를 만들 클래스의 결정은 서브 클래스 쪽에서 결정하도록 한다.
객체 인스턴스를 생성하는 (new 키워드 사용 부분)을 별도의 인터페이스로 분리하고, 이를 객체를 만들어내는 공장(factory)로 활용한다.
여러개의 서브 클래스를 가진 수퍼 클래스가 있을때, 들어오는 인자에 따라서 하나의 서브 클래스의 인스턴스를 반환해준다.
객체를 만드는 공장(팩토리 객체)을 만드는 패턴이라고 이해할 수 있다.
팩토리 메소드 패턴을 사용하는 이유는 클래스간의 결합도를 낮추기 위해서다. 클래스의 변경점이 생겼을 때 다른 클래스에 영향을 주는 일을 최소화 해야 한다.
팩토리 메소드 패턴을 사용하는 경우 직접 객체를 생성해 사용하는 것을 방지하고 서브 클래스에 위임함으로써 보다 효율적인 코드 제어를 할 수 있고 의존성을 제거할 수 있다. 결과적으로 결합도 또한 낮출 수 있게 된다.
아래와 같은 로봇 클래스를 작성해준다.
package pattern.factory;
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";
}
}
기본 팩토리 클래스
package pattern.factory;
public abstract class RobotFactory {
abstract Robot createRobot(String name);
}
기본 팩토리 클래스를 상속 받아 실제 로직을 구현한 클래스
package pattern.factory;
public class SuperRobotFactory extends RobotFactory {
@Override
Robot createRobot(String name) {
switch( name ){
case "super": return new SuperRobot();
case "power": return new PowerRobot();
}
return null;
}
}
import java.util.*;
import java.security.*;
interface Food {
public String getType();
}
class Pizza implements Food {
public String getType() {
return "Someone ordered a Fast Food!";
}
}
class Cake implements Food {
public String getType() {
return "Someone ordered a Dessert!";
}
}
class FoodFactory {
//팩토리 메소드 - 객체 생성 후 반환
public Food getFood(String order) {
//Write your code here
if(order == null){
return null;
}
//order타입이 pizza이면 Pizza 클래스의 인스턴스 리턴.
if(order.equals("pizza")){
return new Pizza();
}
//order타입이 cake이면 Cake 클래스의 인스턴스 리턴.
if(order.equals("cake")){
return new Cake();
}
return null;
}//End of getFood method
}//End of factory class
public class JavaFactoryPattern {
public static void main(String args[]){
Do_Not_Terminate.forbidExit();
try{
Scanner sc=new Scanner(System.in);
//creating the factory
FoodFactory foodFactory = new FoodFactory();
//factory instantiates an object
Food food = foodFactory.getFood(sc.nextLine());
System.out.println("The factory returned "+food.getClass());
System.out.println(food.getType());
}
catch (Do_Not_Terminate.ExitTrappedException e) {
System.out.println("Unsuccessful Termination!!");
}
}
}
class Do_Not_Terminate {
public static class ExitTrappedException extends SecurityException {
private static final long serialVersionUID = 1L;
}
public static void forbidExit() {
final SecurityManager securityManager = new SecurityManager() {
@Override
public void checkPermission(Permission permission) {
if (permission.getName().contains("exitVM")) {
throw new ExitTrappedException();
}
}
};
System.setSecurityManager(securityManager);
}
}