팩터리 메서드 패턴 (Factory Method Pattern)

초코칩·2024년 2월 21일
0

Design Pattern

목록 보기
3/5
post-thumbnail

팩터리 메서드

팩터리 메서드는 부모 클래스에서 객체들을 생성할 수 있는 인터페이스를 제공하지만, 자식 클래스들이 생성될 객체들의 유형을 변경할 수 있는 생성 패턴이다.

문제점

현재 대부분의 코드는 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();
    }
}

장단점

장점

  • OCP(개방 폐쇄 원칙): 기존의 코드를 변경하지 않고도 새로운 기능을 추가할 수 있도록 함으로써 확장성을 강화한다. 새로운 요구사항이나 기능 추가 시 기존 코드에 최소한의 영향을 미치게 된다.
  • 코드 중복 감소: 객체 생성 코드가 팩터리 메서드에 중앙집중화되므로 중복 코드를 감소시키고, 일관된 인터페이스를 제공하여 코드의 가독성을 높인다.

단점

  • 추상화 필요: 팩터리 메서드 패턴을 사용하면서 적절한 인터페이스나 추상 클래스를 설계해야 한다. 이를 위해 추가적인 코드 작업이 필요하다.
  • 클래스 계층 구조의 복잡성: 팩터리 메서드 패턴을 적용하면 클래스 계층 구조가 더 복잡해질 수 있다. 즉, 구현 클래스의 수가 늘어나고, 이에 따라 유지보수 및 이해하기 어려워질 수 있다.

Ref

https://refactoring.guru/ko/design-patterns/factory-method

profile
초코칩처럼 달콤한 코드를 짜자

0개의 댓글