들어가기전에 new를 집고 넘어가려고 합니다. 갑자기 디자인 패턴하다가 new라는 키워드설명을 왜 하나요 싶겠지만, 팩토리 패턴과 밀접한 관련이 있습니다.
우리가 객체를 생성할때 보통 객체 객체명 = new 객체생성자()
와 같은 방식으로 new를 이용했습니다. 여기서 new라는 것은 생성자를 통해 객체의 인스턴스를 생성하는 것인데요. 이렇게 생성한다는 것은 구체적으로 작성된 클래스를 통해 구현을 한다는 의미입니다. 그래서 객체와 관련한 수정이 발생하면 일일히 관련 코드들을 고쳐야하기에 유지보수면에서 좋지 못한 모습을 보입니다. 그래서 우리는 new 대신에 다른 방식을 이용하는 것을 생각해야합니다.(당연히 무조건 new를 통한 객체 생성이 나쁘다는 의미는 아닙니다.)
우리가 new 대신 사용할 수 있는 방법은 인터페이스를 이용하는 것 입니다. 인터페이스를 이용하면 어떤 클래스를 구현하든지 간에 인터페이스만 구현하면 문제없이 사용할 수 있고, 코드 수정 또한 용이합니다. 첫 포스트에서 소개한 5원칙 중 OCP:확장 폐쇄원칙
기억하시나요? 바로 코드는 확장에 대해서는 닫혀있고 변화에 대해서는 열려있다라는 것인데, 인터페이스가 이 원칙을 잘 지킬 수 있도록해줍니다.
Factory패턴을 이용하면 new 키워드로 객체를 생성하는 대신 인터페이스를 통해 구현 클래스에서 객체를 생성할 수 있습니다. 그러면 이제부터 팩토리 패턴의 하나인 팩토리 메소드 패턴을 알아보도록하겠습니다.
팩토리 메소드 패턴
의 정의부터 파고들어가 보자면 팩토리 메소드 패턴
은 객체의 생성을 위해서 인터페이스를 정의하지만 객체의 생성에 대해서는 서브클래스가 결정하게 만드는 패턴입니다. 팩토리 메소드 패턴
은 생성 패턴에 속하고 있습니다.
대부분의 프로그래밍 개념들이 그렇지만 역시 글로 읽기만 하는 것 보다는 실제로 사용해봐야 정확히 알 수 있겠죠?
예시로 비행기 공장 예시를 한 번 들어볼까 합니다. 비행기는 기본적으로 이륙하고, 날고, 착륙합니다. 그래서 인터페이스 이 기본적인 비행기의 뼈대를 만들었습니다. 이 인터페이스는 Product라고 해서 우리가 팩토리 패턴으로 만들어낼 객체에 해당합니다.
package Factory;
public interface Airplane {
public void takeOff();
public void fly();
public void land();
}
다음은 이 인터페이스를 기반으로 만드는 비행기 공장 추상 클래스입니다. 우리는 이 클래스를 Creater라고 하며 이 클래스 내부의 생성 메소드를 팩토리 메소드라고 합니다. 왜냐하면 저 생성담당 메소드가 실제로 객체들을 생성해 주기 때문이죠.
package Factory;
abstract class AirplaneFactory {
public Airplane preparingAirplane(String planeType) {
Airplane airplane = createAirplane(planeType);
airplane.takeOff();
airplane.fly();
airplane.land();
return airplane;
}
//생성담당
abstract Airplane createAirplane(String planeType);
}
공장을 만들었으니 이번에는 여객기와 전투기 두 개의 비행기 클래스를 구현해보겠습니다. 이 두 메서드가 팩토리 메소드를 구현한 클래스가 됩니다. 아까 처음에 서브 클래스에서 객체의 생성을 담당한다고 했는데 바로 여기서 객체가 생성됩니다.
package Factory;
public class Airliner extends AirplaneFactory {
@Override
Airplane createAirplane(String planeType) {
return null;
}
}
package Factory;
public class Fighter extends AirplaneFactory {
@Override
Airplane createAirplane(String planeType) {
return null;
}
}
각 클래스의 메소드에서 return
부분을 주목해보아야 합니다. return null 부분을 어떻게 수정하냐에 따라서 여러 다른 객체들이 탄생합니다. 예를 들면 여객기인 airliner는 보잉 여객기라던가 에어버스 여객기라던가로 바꿀 수 있는 등 다양한 조작이 가능합니다.
실 사용은 다음과 같은 형태로 사용합니다.
package Factory;
public class AirPortSystem {
public static void main(String[] args) {
AirplaneFactory airlinerFact = new Airliner();
AirplaneFactory fighterFact = new Fighter();
Airplane airplane1 = airlinerFact.createAirplane("보잉");
Airplane airplane2 = fighterFact.createAirplane("F-15");
}
}