Factory Method
구체적으로 어떤 인스턴스를 만들지는 서브 클래스가 정한다.
다양한 구현체(Product)가 있고, 그 중에서 특정한 구현체를 만들 수 있는 다양한 팩토리(Creator)를 제공할 수 있다.
확장에는 열려 있고 변경에 닫혀 있는 구조
Ship이라는 객체가 있을 때 이를 상속받는 WhiteShip, BlackShip이 있고,
Ship을 생성하는 ShipFactory는 BlackshipFactory, WhiteshipFactory를 상속한다.
팩토리 메소드를 사용하는 경우
새로운 객체가 만들어질 때마다 해당 생성 factory를 생성하여 ShipFactory를 상속받도록하여
객체 생성(확장)에 유연성을 준다.
Ship
public class Ship {
private String name;
private String color;
private String logo;
public String getName() {
return name;
}
public String getColor() {
return color;
}
public String getLogo() {
return logo;
}
public void setName(String name) {
this.name = name;
}
public void setColor(String color) {
this.color = color;
}
public void setLogo(String logo) {
this.logo = logo;
}
}
public class WhiteShip extends Ship{
public WhiteShip(){
setName("whiteShip");
setLogo("\uD83D\uDEE5");
setColor("white");
}
}
public class BlackShip extends Ship{
public BlackShip(){
super.setName("blackShip");
super.setLogo("");
super.setColor("black");
}
}
ShipFactory
public interface ShipFactory {
default Ship orderShip(String name, String email){
validate(email);
prepareFor(name);
Ship ship = createShip();
sendEmailTo(email, ship);
return ship;
}
Ship createShip();
private void sendEmailTo(String email, Ship ship){
System.out.println(ship.getName() + " 다 만들었습니다. ");
}
private void validate(String email){
// validate
if(email == null || email.isBlank()){
throw new IllegalArgumentException("연락처를 남겨주세요");
}
}
private static void prepareFor(String name) {
System.out.println(name + " 만들 준비 중");
}
}
public class WhiteShipFactory implements ShipFactory {
@Override
public Ship createShip() {
return new WhiteShip();
}
}
public class BlackShipFactory implements ShipFactory{
@Override
public Ship createShip() {
return new BlackShip();
}
}
public class Client {
public static void main(String[] args) {
Client client = new Client();
client.print(new WhiteShipFactory(), "whiteShip", "client@mail.com" );
client.print(new WhiteShipFactory(), "blackShip", "client@mail.com" );
}
private void print(WhiteShipFactory shipFactory, String name, String email) {
System.out.println(shipFactory.orderShip(name, email));
}
}
[ 패턴복습 ]
1. 팩토리 메소드 패턴을 적용했을 때의 장점과 단점은?
- 장점: 확장에는 열려있고, 수정에 닫혀있다. 즉, 관련 기능에 대해 새롭게 추가하거나 늘려갈 때는 기존의 코드를 활용하여 확장하기 쉽지만, 각각의 생성되는 인스턴스 내부의 수정은 독립적이다.
(기존 코드를 건드리지 않고(코드 간결) 유사한 새로운 인스턴스를 다른 방법으로 얼마든지 확장이 가능하다.) - 느슨한 결합 (Loose Coupling)
- 단점: 코드가 길어진다. 역할을 나누다 보니 클래스가 늘어난다.
2. "확장에 열려있고 변경에 닫혀잇는 객체 지향 원칙"은?
- OCP(Open closed principle)
- 변경에 닫혀있다 -> 기존 코드를 변경하지 않으면서 새로운 기능을 얼마든지 확장할 수 있는 구조를 만든다.
3. 자바 8에 추가된 default 메소드란 무엇인가?
- default 메소드는 인터페이스에서도 default를 선언하여 코드를 구현할 수 있는 메소드를 의미한다. 본래 인터페이스는 선언하는 역할이지만, 간혹 이미 사용하고 있는 인터페이스에 기능을 확장해야 하는 경우 에러나 버그를 줄이기 위해 새로운 코드를 구현하여 사용할 수 있도록 한다. 이를 '하위호환성' 이라 하며, default 메소드를 사용할 경우 하위호완성은 유지되고 인터페이스의 보완을 진행할 수 있다.
'Design Patterns > 생성(Creational)' 카테고리의 다른 글
[Builder]빌더패턴 (0) | 2022.05.26 |
---|---|
[Abstract factory]추상팩토리 (0) | 2022.05.25 |
[Singleton]4. 자바와 스프링에서 찾아보는 패턴 (0) | 2022.04.08 |
[Singleton]3. 안전하고 단순하게 구현하는 방법 (0) | 2022.04.07 |
[Singleton]2. 패턴 구현 깨트리는 방법 (0) | 2022.04.05 |