S E P H ' S

[생성 패턴] 추상 팩토리 (Abstract Factory) 패턴 본문

Programing & Coding/Design Pattern

[생성 패턴] 추상 팩토리 (Abstract Factory) 패턴

yoseph0310 2023. 3. 5. 17:46

추상 팩토리(Abstract Factory) 패턴

팩토리 메소드 패턴에서는 하나의 팩토리 클래스가 인풋으로 들어오는 값에 따라 if-else, switch문을 사용하여 다양한 서브 클래스를 리턴하는 식으로 구현했다.

 

추상 팩토리 패턴에서는 팩토리 클래스에서 서브 클래스를 생성하는 데 있어 if-else 문을 걷어낸다.

추상 팩토리 패턴은 인풋으로 서브 클래스에 대한 식별 데이터를 받는 것이 아닌 또 하나의 팩토리 클래스를 받는다.

 

 

Super Class

 

public abstract class Computer {
    
    public abstract String getRAM();
    public abstract String getHDD();
    public abstract String getCPU();

    @Override
    public String toString() {
        return "RAM= "+this.getRAM()+", HDD="+this.getHDD()+", CPU="+this.getCPU();
    }
}

 

 

Sub Class - 1

 

public class PC extends Computer {

    private String ram;
    private String hdd;
    private String cpu;

    public PC(String ram, String hdd, String cpu) {
        this.ram = ram;
        this.hdd = hdd;
        this.cpu = cpu;
    }

    @Override
    public String getRAM() {
        return null;
    }

    @Override
    public String getHDD() {
        return null;
    }

    @Override
    public String getCPU() {
        return null;
    }
}

 

 

Sub Class - 2

 

public class Server extends Computer{
    
    private String ram;
    private String hdd;
    private String cpu;

    public Server(String ram, String hdd, String cpu) {
        this.ram = ram;
        this.hdd = hdd;
        this.cpu = cpu;
    }

    @Override
    public String getRAM() {
        return null;
    }

    @Override
    public String getHDD() {
        return null;
    }

    @Override
    public String getCPU() {
        return null;
    }
}

 

여기까지는 팩토리 패턴과 같지만 지금부터 차이가 난다.

먼저 추상 팩토리의 역할을 하는 인터페이스 혹은 추상 클래스가 필요하다.

 

AbstractFactory

 

public interface ComputerAbstractFactory {
    
    public Computer createComputer();
    
}

 

여기서 주의를 기울여야 하는 것은 팩토리 인터페이스의 createComputer() 메소드의 리턴 타입이 상위 클래스인 Computer 라는 것이다. 이제 이 팩토리 인터페이스를 구현하는 클래스에서 createComputer()를 오버라이딩 하여 각각의 서브 클래스를 리턴해줄 것이다. 이는 자바의 다형성을 잘 활용한 방식이다.

 

 

PCFactory

 

public class PCFactory implements ComputerAbstractFactory {
    
    private String ram;
    private String hdd;
    private String cpu;

    public PCFactory(String ram, String hdd, String cpu) {
        this.ram = ram;
        this.hdd = hdd;
        this.cpu = cpu;
    }

    @Override
    public Computer createComputer() {
        return new PC(ram, hdd, cpu);
    }
}

 

 

ServerFactory

 

public class ServerFactory implements ComputerAbstractFactory {
    
    private String ram;
    private String hdd;
    private String cpu;

    public ServerFactory(String ram, String hdd, String cpu) {
        this.ram = ram;
        this.hdd = hdd;
        this.cpu = cpu;
    }

    @Override
    public Computer createComputer() {
        return new Server(ram, hdd, cpu);
    }
}

 

이렇게 하여 두 서브 클래스에 대한 팩토리 클래스인 PCFactory와 ServerFactory를 구현했다. 이제 마지막으로 이 서브 클래스들을 생성하기 위해 클라이언트 코드에 접점으로 제공되는 컨슈머 클래스를 만들것이다.

 

public class ComputerFactory {
    
    public static Computer getComputer(ComputerAbstractFactory factory) {
        return factory.createComputer();
    }
}

 

이제 클라이언트는 이 ComputerFactory 클래스의 getComputer() 라는 static 메소드에 앞서 구현한 PCFactory, ServerFactory 인스턴스를 넣어줌으로써 if-else 없이도 각각 원하는 서브 클래스의 인스턴스를 생성할 수 있게 되었다.

 

public class AbstractFactoryTest {
    public static void main(String[] args) {
        Computer pc = ComputerFactory.getComputer(new PCFactory("2 GB", "500 GB", "2.4 GHz"));
        Computer server = ComputerFactory.getComputer(new ServerFactory("16 GB", "2 TB", "2.9 GHZ"));
        System.out.println("AbstractFactory PC : " + pc);
        System.out.println("AbstractFactory Server : " + server);
    }
}

 

추상 팩토리 패턴의 장점

  1. 추상 팩토리 패턴은 구현보다 인터페이스를 위한 코드 접근법을 제공한다. 위 예에서 getComputer() 메소드는 파라미터로 인터페이스를 받아 처리 하기 때문에 getComputer()에서 구현할 것이 복잡하지 않다.
  2. 추상 팩토리 패턴은 추후에 서브 클래스를 확장하는데 있어 굉장히 쉽게 할 수 있다. 위 예에서 만약 Laptop 클래스를 추가하고자 한다면 getComputer()의 수정 없이 LaptopFactory 만 작성하면 된다. 이러한 특징으로 추상 팩토리 패턴은 "Factory of Factories"라고 불리기도 한다.
  3. 추상 팩토리 패턴은 팩토리 패턴의 조건문으로 부터 벗어난다.

 

 

출처 : https://readystory.tistory.com/119