Computer Science

Factory Method Pattern | 팩토리 메서드 패턴

연_우리 2022. 7. 29. 21:36
반응형

 

 

 

어떤 상황에서 쓰일까?

하얀배는 하얀색깔에, 하얀마크에, whiteship이라는 이름을 가지고있다.

검정배는 검정색깔에, 검정마크에, blackship이라는 이름을 가지고있다.

노란배는 하얀배, 검정배와 동일한 작업에 내용물만 바꾸어 만들 수 있다.

 

배를 만드는 코드가 if문으로 분기처리 되어있으면

초록배를 만들어야할 경우 분기처리가 4개나 이루어지게되어 깔끔한 코드가 아닐것이고,

계속 코드를 수정해야하니 확장에 유연하지도 않게된다.

 

배의 공통적인 color, mark, name을 지정할 수 있도록 팩토리를 지정하고,

팩토리로부터 하얀배, 검정배, 노란배를 만들 수 있도록 하면 어떨까??

 

 

 

팩토리 메서드 패턴이란?

구체적으로 어떤 인스턴스를 만들지는 서브 클래스가 정하게하는 패턴이다

 

장점

- 확장에 열려있고 변경에 닫혀있는 객체지향원칙 OCP를 지킬 수 있다

- 기존의 코드, 특히 인스턴스를 만드는 코드를 건들이지 않고 새로운 인스턴스를 만들 수 있다

 

 

단점

- 인스턴스가 추가될때마다 클래스 파일이 계속 생성된다

 

 

 

구현방법

기존코드

public class ShipFactory {

    public static Ship orderShip(String name, String email) {
    
        //validate
        if (name == null || name.isBlank()) {
            throw new IllegalArgumentException("배 이름을 지어주세요.");
        }
        if (email == null || email.isBlank()) {
            throw new IllegalArgumentException("연락처를 남겨주세요.");
        }
    
    
        Ship ship = new Ship();
        ship.setName(name);

        // Customizing for specific name
        if (name.equalsIgnoreCase("whiteship")) {
            ship.setLogo("\uD83D\uDEE5️");
        } else if (name.equalsIgnoreCase("blackship")) {
            ship.setLogo("⚓");
        }

        // coloring
        if (name.equalsIgnoreCase("whiteship")) {
            ship.setColor("white");
        } else if (name.equalsIgnoreCase("blackship")) {
            ship.setColor("black");
        }

        return ship;
    }
}

 

 

 

변경코드

ShipFactory 클래스를 인터페이스로 변경하고

이름, 로고, 색깔을 지정하는 것은 인터페이스를 상속받은 클래스로 변경한다

public interface ShipFactory {

    default Ship orderShip(String name, String email) {
        validate(name, email);
        Ship ship = createShip();
        return ship;
    }
    
    
    //구현 클래스에서 구현할 메서드
    Ship createShip();

    //공통적으로 쓰이는 유효성검사 메서드
    private void validate(String name, String email) {
        if (name == null || name.isBlank()) {
            throw new IllegalArgumentException("배 이름을 지어주세요.");
        }
        if (email == null || email.isBlank()) {
            throw new IllegalArgumentException("연락처를 남겨주세요.");
        }
    }
    
}
public class WhiteshipFactory implement ShipFactory {

    @Override
    public Ship createShip() {
        return new Whiteship();
        
        //해당 예제코드에서는 new Whiteship()을 만들어서 반환해주기만 하면되지만
        //만약 나중에 하얀색 배는 100kg까지 적재해야하고, 검정색 배는 150kg까지 적재해야한다는 조건이 추가되면 
        //WhiteshipFactory클래스에서 validation처리를 해주어야한다!
    }
}
public class Whiteship extends Ship {

    public Whiteship() {
        setName("whiteship");
        setLogo("\uD83D\uDEE5️");
        setColor("white");
    }
    
}
public class Client {

    public static void main(String[] args) {
        Client client = new Client();
        client.print(new WhiteshipFactory(), "whiteship", "keesun@mail.com");
        client.print(new BlackshipFactory(), "blackship", "keesun@mail.com");
    }

    //ShipFactory를 받기때문에 YellowshipFactory가 생긴다해도 print메서드는 변함이 없다
    private void print(ShipFactory shipFactory, String name, String email) {
        System.out.println(shipFactory.orderShip(name, email));
    }

}

 

 

여기서 Blackship을 만들때, Whiteship의 코드를 수정할 이유가 있을까??? 없다!

Whiteship과 동일하게 BlackshipFactory, Blackship을 생성해주기만 하면 된다!

변경에는 닫혀있고 확장에는 열려있는 코드가 완성되었다~!

 

 

 

 

 

 

 

 

 

 

반응형

'Computer Science' 카테고리의 다른 글

Prototype Pattern | 프로토타입 패턴  (0) 2022.08.14
Abstract Factory | 추상 팩토리 패턴  (0) 2022.08.14
Singleton pattern | 싱글톤패턴  (3) 2022.07.29
운영체제 개요  (0) 2022.03.25
프로세스? 스레드?  (0) 2022.02.17
  • 네이버 블러그 공유하기
  • 페이스북 공유하기
  • 트위터 공유하기
  • 구글 플러스 공유하기
  • 카카오톡 공유하기