(인프런) 코딩으로 학습하는 GoF의 디자인 패턴 - 백기선, 강의를 보고 정리한 글입니다.
코드는 GitHub 에 있습니다
#1. 객체 생성 관련 패턴 |
#2. 구조 관련 패턴 |
#3. 행동 관련 패턴 |
||
✔️ 팩토리 메소드 패턴
- 구체적으로 어떤 인스턴스를 만들지를 서브 클래스가 정하는 패턴을 말합니다.
- 팩토리 메소드 패턴은, 기능혹은 역할에 따른 다양한 구현체가(Product) 가 존재하고, 그 중에서 특정한 구현체를 만들 수 있는 다양한 팩토리(Creator)를 제공할 수 있습니다.
✔️ 팩토리 메소드 패턴 구현방법
- 팩토리 메소드 패턴의 목적은 "변경에는 닫혀있고, 확장에는 열려있는 구조" 를 만드는 것입니다. 즉, OCP 원칙을 지키기위한 패턴에 가깝다고 생각합니다.
📌 1) 예시 코드
- black 배와 white 배를 만드는 factory가 아래와 같이 정의되어있다고 가정합니다.
Ship.class
@Setter
@ToString
public class Ship {
private String name;
private String email;
private String color;
}
Factory.class
public class ShipFactory {
public static Ship orderShip(final String name, final String email) {
//validate
if (Objects.isNull(name) || name.isBlank()) {
throw new IllegalArgumentException("배 이름을 지어주세요");
}
if (Objects.isNull(email) || email.isBlank()) {
throw new IllegalArgumentException("연락처를 남겨주세요");
}
Ship ship = new Ship();
ship.setName(name);
if (name.equalsIgnoreCase("whiteship")) {
ship.setColor("white");
}
if (name.equalsIgnoreCase("blackship")) {
ship.setColor("black");
}
return ship;
}
}
클라이언트에서 white ship을 만들것인가, black ship을 만들 것인가에 따라 반환되는 ship 이 달라지는 코드입니다.
public class Client {
public static void main(String[] args) {
Client client = new Client();
Ship whiteShip = ShipFactory.orderShip("WhiteShip", "one@email.com");
System.out.println("whiteShip = " + whiteShip.toString());
Ship blackShip = ShipFactory.orderShip("blackShip", "two@email.com");
System.out.println("blackShip = " + blackShip.toString());
}
}
Factory 를 통해 요구조건에 따라 다른 Ship 객체가 반환되지만, 만약 요구사항이 변경된다면 Factory 코드가 변경되어야만 합니다.
💡 즉 이 코드는, 변경에 닫혀있지 않은 코드인 것이죠
📌 2) 팩토리 메서드 패턴으로 변경
1. 먼저 배를만드는, Factory 를 Interface 로 구현합니다.
- 기존에 ShipFactory에서 진행하던 validate도 ShipFactory로 하며, 배를 직접적으로 생성시키는 createShip( ) 메소드만 추상메소드로 정의합니다.
public interface ShipFactory {
default Ship orderShip(String name, String email) {
validate(name, email);
return createShip();
}
Ship createShip();
private void validate(String name, String email) {
//validate
if (Objects.isNull(name) || name.isBlank()) {
throw new IllegalArgumentException("배 이름을 지어주세요");
}
if (Objects.isNull(email) || email.isBlank()) {
throw new IllegalArgumentException("연락처를 남겨주세요");
}
}
}
2. 그 다음, 직접적으로 배를 만들어 반환하는 createShip() 메서드를 구현하는 구현체를 각각 책임에 맞게 정의합니다.
public class WhiteShipFactory implements ShipFactory{
@Override
public Ship createShip() {
return new WhiteShip();
}
}
public class WhiteShip extends Ship {
public WhiteShip() {
setName("whiteShip");
setLogo("white");
setEmail("whiteLogo");
}
}
public class BlackShipFactory implements ShipFactory{
@Override
public Ship createShip() {
return new BlackShip();
}
}
public class BlackShip extends Ship {
public BlackShip() {
setName("BlackShip");
setLogo("Black");
setEmail("BlackLogo");
}
}
3. 클라이언트에서 만들 배에 따라서, 해당하는 구현체를 선택해줍니다.
public class Client {
public static void main(String[] args) {
Ship whiteShip =new WhiteShipFactory().orderShip("WhiteShip", "one@email.com");
System.out.println("whiteShip = " + whiteShip.toString());
Ship blackShip = new BlackShipFactory().orderShip("blackShip", "two@email.com");
System.out.println("blackShip = " + blackShip.toString());
}
}
👏🏻 여기서 중요한 것은, 다음 RedShip, BludShip 등,, 요구사항 변경에의해 추가적인 배 객체를 만들어야해도, 기존코드를 수정하는 것이 아니라, createShip()메소드를 구현하는 구현체만 추가해주면 됩니다.
즉 변경에는 닫혀있고, 확장에는 열려있는 OCP 를 지키는 구조가 되어집니다.
→ 클라이언트의 변경도 최소하고 싶다면, 구현체를 선택하는 계층을 하나 더 두거나, 외부에서 구현체를 주입받거나 하는 구조로 변경을 하는 방법이 존재합니다.
✔️ 팩토리 메소드 패턴 복습
1. 팩토리 메소드 패턴의 장점 및 단점
- 장점
- 요구사항의 변경에도 기존코드를 변경하지 않고 확장하여 처리할 수 있는 보기좋은 구조가 됩니다.
- 이는, product와 creater간에 관계를 느스한 결합으로 묶었기 때문에 가능한 것입니다.
- 단점
- 각자의 역할을 가지고있는 클래스가 늘어남은 맊을 수 없다. (관리 포인트의 증가)
2. "확장에 열려있고 변경에 닫혀있는 객체 지향 원칙"을 설명하세요
- 변경에 닫혀있다 : 기존 코드를 변경하지 않는다,
- 확장에 열려있다 : 새로운 코드를 얼마든지 확장한다.
3. 자바 8에 추가된 default 메소드에 대해 설명하세요.
- 기존 자바 버전에서는 interface 에는 추상메소드만이 선언 가능했지만,
- 자바 8 이후부터는, 기본 메소드를 정의할 수 있기 때문에, 추상 메소드를 상속받는 모든 구현체에서 필요한 기능을 상속받을 수 있도록 되었습니다.
끝!
'Java > Design Pattern' 카테고리의 다른 글
[디자인 패턴] 구조 패턴 - 어댑터 패턴 (Adapter Patterns) (0) | 2023.02.16 |
---|---|
[디자인 패턴] 생성패턴 - 프로토타입 패턴 (Prototype Patterns) (0) | 2023.02.15 |
[디자인 패턴] 생성패턴 - 빌더 패턴 (Builder Patterns) (0) | 2023.02.10 |
[디자인 패턴] 생성패턴 - 추상 팩토리 패턴 (Abstract Factory patterns) (0) | 2023.02.09 |
[디자인 패턴] 생성패턴 - 싱글톤 패턴이란 (Singleton patterns) (0) | 2023.02.08 |