[CS] 팩토리 메서드 패턴

이준기·2022년 10월 22일
0

Factory Method(팩토리 메서드) 패턴


  • Factory 패턴은 객체 생성 역할을 별도의 클래스 (Factory) 에게 위임하는 것이 가장 궁극적인 목표 → 클래스간 결합도(의존성)를 낮춤으로써 객체지향적 설계
  • 디자인 패턴 중 Factory 와 관련된 패턴은 팩토리 메서드 패턴추상 팩토리 패턴이 존재함
  • 이 두 가지 패턴의 베이스가 되는 가장 단순한 형태가 Simple Factory 패턴

Simple Factory 패턴

public interface Phone {
}

public class Iphone implements Phone {
}

public class Galaxy implements Phone {
}
Phone iphone = new Iphone();
Phone galaxy = new Galaxy();

객체는 여러 곳에서 생성될 수 있는데, 호출하는 쪽이 객체의 생성자에 직접 의존하고 있으면 나중에 요구사항이 변경되었을 때 호출 코드가 모두 직접 수정되어야 하는 경우가 많이 발생하게된다.

public interface Phone {
    enum Type {
        IPHONE, GALAXY
    }
}

public class PhoneFactory {

    public Phone createPhone(Phone.Type phoneType) {
        switch (phoneType) {
            case IPHONE:
                return new Iphone();
            case GALAXY:
                return new Galaxy();
            default:
                throw new IllegalArgumentException("Phone 타입이 아닙니다");
        }
    }
}

PhoneFactory phoneFactory = new PhoneFactory();
Phone iphone = phoneFactory.createPhone(Phone.Type.IPHONE);
Phone galaxy = phoneFactory.createPhone(Phone.Type.GALAXY);

그래서 생성자 호출 (new) 을 별도의 클래스 (Factory) 에서 담당하고 호출 코드에서는 팩토리를 통해 객체를 생성한다.

PhoneFactory를 선언한 후 생성 메서드만 호출하면 실제 구현 클래스인 IphoneGalaxy에 의존하지 않은 코드를 작성할 수 있게 된다!

→ 하지만 새로운 phone 클래스로 Zplip 이 추가된다면 PhoneFactory 내부를 수정해야하므로, 기존 코드에 영향을 주지 않는 것을 지향하는 객체지향 원칙을 지키기 힘들다. (OCP 원칙)

Factory Method 패턴

public interface Phone {
    void register();
}

public class Iphone implements Phone {
    @Override
    public void register() {
        System.out.println("아이폰 유저 입니다."); // iphone 전용 로직
    }
}

public abstract class PhoneFactory {

    public Phone newInstance() {
        Phone phone = createPhone();
        phone.register();
        return phone;
    }

    protected abstract Phone createPhone();
}

public class IphoneFactory extends PhoneFactory {
    @Override
    protected Phone createPhone() {
        return new Iphone();
    }
}

public class ZFlipFactory extends PhoneFactory {
    @Override
    protected Phone createPhone() {
        return new ZFlip();
    }
}

팩토리를 추상 클래스로 정의하여, 실제로 어떤 객체를 생성할 지는 추상 메서드로 정의해서 하위 클래스에서 정의

PhoneFactory phoneFactory = new IphoneFactory();
Phone phone = phoneFactory.newInstance();
  • 호출 코드에서 Iphone 클래스에 대한 의존성 없이 사용 가능
  • 의존성 주입을 사용해서 외부에서 Factory 클래스를 받아온다면 PhoneFactory 에 대한 의존성도 제거 가능

→ 새로운 phone 클래스로 Zplip 이 추가될때, 기존 코드의 변경 없이 phone 인터페이스와 ZplipPhoneFactory 를 새로 정의하여 확장 가능

→ 확장때마다 많은 클래스를 정의하여야 하기 때문에 코드량이 증가한다는 단점이 있음

Abstract method 패턴

public interface PhonePartsFactory {
    Cpu createCpu();
    Speaker createSpeaker();
}

서로 연관된 또는 의존적인 객체(parts)들을 모아서 인터페이스로 제공함. 각 phone 클래스(서브 클래스)에서는 parts 들을 오버라이딩하여 사용!

→ 팩토리 메서드 패턴과 비슷하지만 공통된 집합을 모아둔다는 점이 특징임

Reference

https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/DesignPattern

https://bcp0109.tistory.com/367

profile
Hongik CE

0개의 댓글