구체적으로 어떤 인스턴스를 만들지는 서브 클래스가 정한다
다양한 구현체(Product)가 있고, 그중에서 특별한 구현체를 만들 수 있는 다양한 팩토리(Creator)를 제공할 수 있다.
확장에 열려있고 변경에 닫혀있는 구조로 만들어보자
public interface ShipFactory {
default Ship orderShip(String name, String email) {
validate(name, email);
prepareFor(name);
Ship ship = createShip();
sendEmailTo(email, ship);
return ship;
}
void sendEmailTo(String email, Ship 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("연락처를 남겨주세요.");
}
}
private void prepareFor(String name) {
System.out.println(name + " 만들 준비 중");
}
}
먼저 ShipFactory 인터페이스를 만든다. ShipFactory는 Ship을 만드는 Creator역할을 하는 인터페이스이다. 기본적으로 Ship을 주문하고 만드는데 만드는 로직인 createShip 함수는 서브클래스에 구현을 하여 서브클래스가 결정하도록 한다.
public abstract class DefaultShipFactory implements ShipFactory {
@Override
public void sendEmailTo(String email, Ship ship) {
System.out.println(ship.getName() + " 다 만들었습니다.");
}
}
public class BlackShipFactory extends DefaultShipFactory {
@Override
public Ship createShip() {
return new Blackship();
}
}
public class WhiteShipFactory extends DefaultShipFactory {
@Override
public Ship createShip() {
return new Whiteship();
}
}
DefaultShipFactory는 ShipFactory를 상속받는 추상 클래스인데, 만약 자바 8 이상을 사용하고 있다면 인터페이스에 default 함수를 만들 수 있으므로 이 경우 생략이 가능하나 그 이하의 버전을 사용하고 있다면 default 함수는 중간에 추상클래스를 추가하여 작성해줘야 한다.
DefaultShipFactory를 상속하는 BlackShipFactory와 WhiteShipFactory는 구현클래스이다. 이 구현클래스가 직접 Ship을 만드는 로직을 구현하여 클라이언트에서는 원하는 Factory를 선택하여 원하는 객체를 만들 수 있다.
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");
}
private void print(ShipFactory shipFactory, String name, String email) {
System.out.println(shipFactory.orderShip(name, email));
}
}
클라이언트 코드를 보면 원하는 Factory를 선택하여 Ship을 만드는 것을 볼 수 있다.
질문
- 팩토리 메소드 패턴을 적용했을 때의 장점과 단점은? : 팩토리 메소드 패턴을 사용할 경우 기본의 if문이나 switch문으로 분기처리하여 로직을 작성했던 것을 클라이언트에서 원하는 방식을 선택하게 하여 분기처리 없이 로직을 추가할 수 있다. 단점은 새로운 로직이 추가될때마다 클래스를 추가해줘야 한다
- 확장에 열려있고 변경에 닫혀있는 객체 지향 원칙을 설명하세요 : 확장에 열려있고 변경에 닫혀있다는 것은 기존코드를 건드리지 않고 인터페이스를 구현하는 새로운 클래스를 작성하여 새로운 로직을 작성하는 것이다
- 자바 8에 추가된 default 메소드에 대해 설명하세요 : default 메소드는 인터페이스를 상속받는 모든 클래스에 공통으로 사용할 함수를 작성할 때 사용하며 하위 클래스는 해당 함수를 그대로 사용할 수 있고 오버라이딩도 가능하다
'java' 카테고리의 다른 글
Design Patterns - Builder (0) | 2021.11.21 |
---|---|
Design Patterns - Abstract Factory (0) | 2021.11.20 |
Design Patterns - Singleton (0) | 2021.11.11 |
함수형 인터페이스를 이용한 Builder (0) | 2021.05.29 |
더 자바(java 8) - CompletableFuture (0) | 2021.05.26 |
댓글