팩터리 메서드는 부모 클래스에서 객체들을 생성할 수 있는 인터페이스를 제공하지만, 자식 클래스들이 생성될 객체들의 유형을 변경할 수 있는 생성 패턴이다.
현재 대부분의 코드는 Truck 클래스에 결합되어 있다고 가정하자. 앱에 Ship(선박) 클래스를 추가하려면 전체 코드 베이스를 변경해야 한다. 또한 차후 앱에 다른 유형의 교통수단을 추가하려면 아마도 다시 전체 코드 베이스를 변경해야 할 것이다.
그러면 결과적으로 많은 조건문이 운송 수단 객체들의 클래스에 따라 앱의 행동을 바꾸는 매우 복잡한 코드가 작성될 것이다.
팩토리 메서드 패턴은 (new 연산자를 사용한) 객체 생성 직접 호출들을 특별한 팩토리 메서드에 대한 호출들로 책임을 넘길 수 있다. 객체들은 여전히 new 연산자를 통해 생성되지만 팩토리 메서드 내에서 호출된다.
또한 Truck 객체들을 따로 관리하는 것이 아닌, 하나의 Transport 인터페이스를 통해 관리하면 일괄적으로 관리할 수 있다.
이를 통해 Logistics 인터페이스에서 createTransport()
를 통해 생성을 위임할 수 있다.
Truck과 Ship이 따로 생성되어 사용된다.
class Truck {
public Truck() {
// ...
}
public int deliver() {
// ...
}
}
class Ship {
public Ship() {
// ...
}
public int deliver() {
// ...
}
}
class Application {
public static void main(String[] args){
Truck truck = new Truck();
truck.deliver();
Ship ship = new Ship();
ship.deliver();
}
}
이를 위해 하위 클래스들의 객체를 생성하는 팩터리 메서드를 고려할 수 있다. 아래 코드에서 TransportFactory
클래스는 객체 생성을 담당하며, 이를 통해 Application에서는 원하는 수송 수단을 생성하고 사용할 수 있다. 이렇게 하면 코드의 중복이 감소하고, 새로운 수송 수단을 추가하거나 수정할 때도 유연하게 대처할 수 있다.
interface Transport {
int deliver();
}
class Truck implements Transport {
public Truck() {
// ...
}
@Override
public int deliver() {
// ...
}
}
class Ship implements Transport {
public Ship() {
// ...
}
@Override
public int deliver() {
// ...
}
}
class TransportFactory {
public static Transport createTransport(String type) {
if ("Truck".equalsIgnoreCase(type)) {
return new Truck();
} else if ("Ship".equalsIgnoreCase(type)) {
return new Ship();
}
// 추가적인 수송 수단이 있다면 여기에 추가 가능
return null;
}
}
class Application {
public static void main(String[] args) {
// Truck 객체 생성 및 배송
Transport truck = TransportFactory.createTransport("Truck");
int truckResult = truck.deliver();
// Ship 객체 생성 및 배송
Transport ship = TransportFactory.createTransport("Ship");
int shipResult = ship.deliver();
}
}