팩토리 패턴은 객체를 생성하는 코드를 캡슐화하여 클라이언트 코드로부터 분리한는 패턴입니다.
이러한 특성은 객체 지향의 5원칙 SOLID에서 개방 폐쇄 원칙(OCP)을 따릅니다.
확장에 있어서는 열려 있어야 하며, 수정에 있어서는 닫혀 있어야 한다는 것 입니다.
추상 클래스 (abstract class) 란 ?
- 동작이 정의되지 않은 추상 메서드를 포함하는
이러한 추상 클래스를 상속받는 모든 서브클래스는 추상 메서드를 구현해야만 인스턴스를 생성할 수 있습니다.
추상 클래스와 메서드 오버라이딩을 통해 팩토리 패턴을 구현하고 있는 예제 코드입니다. (27-28p)
abstract class Coffee { // 추상 클래스
public abstract int getPrice(); // 동작이 정의되지 않은 추상메서드 => 실제 구현은 하위 클래스에서
@Override
public String toString() {
return "Hi this coffee is" + this.getPrice();
}
} /* toString() 메서드는 자바의 모든 클래스가 기본적으로 상속받는
Object 클래스에 정의된 메서드
* 위처럼 자바에서 toStirng() 메서드를 오버라이드하는 경우,
해당 클래스의 객체를 문자열로 변환할 때, 텍스트의 구조를 정의할 수 있다.
* 원하는 방식대로 문자열 반환할 수 있음
*/
class CoffeeFactory { // 팩토리 클래스 (단일 클래스)
public static Coffee getCoffee(Sring type, int price) { // Coffee 추상 클래스의 인스턴스를 생성하고 반환하고 있다.
if ("Latte".equalsIgnoreCase(type))
return new Latte(price);
else if ("Americano".equalsIgnoreCase(type))
return new Americano(price);
else {
return nes DefaultCoffee();
}
}
}
class DefaultCoffee extends Coffee { // 서브클래스
private int price; // 추상 클래스를 상속받는다.
public DefaultCoffee() {
this.price = -1;
}
@Override // --- 서브 클래스 생성시마다 메서드 재정의
public int getPrice() { // 상위 클래스의 getPrice() 메서드를 오버라이드하여
return this.price;
}
}
class latte extends Coffee { // 서브클래스
private int price;
public Latte(int price) {
this.price = prcie;
}
@Override // --- 서브 클래스 생성시마다 메서드 재정의
public int getPrice() {
return this.price;
}
}
.
.
.
위 코드에서의 핵심 개념은 CoffeeFactory 클래스입니다.
해당 팩토리 클래스는 객체 생성을 캡슐화하여 클라이어언트가 직접 객체를 생성하는 것을 방지하고, 객체 생성의 책임와 역할을 팩토리에 위임합니다.
클라이언트는 CoffeeFactory 클래스의 getCoffee() 메서드를 호출하여 원하는 커피 객체를 얻을 수 있습니다.
추상 팩토리 패턴과 팩토리 메서드 패턴을 추가하게 되면,
새로운 종류의 커피를 추가할 때마다 새로운 하위클래스를 생성하는 대신, 추상 팩토리와 팩토리 메서드를 확장하여 새로운 제품군을 추가할 수 있습니다.
=> 인터페이스를 생성하여 클래스의 갯수를 줄일 수 있습니다.
=> 인터페이스 장점:
(1) 유연성: 구현과는 분리되어있기 때문에, 구현 클래스를 변경하더라도 인터페이스는 동일한 상태 유지 가능하다
(2) 다형성: 인터페이스 타입으로 변수를 선언하고 여러 구현체를 할당할 수 있다.
(3) 결합도 감소: 클라이언트 코드는 인터페이스에만 의존하게 되어, 구체적인 구현 클래스에 직접적으로 의존하지 않게 된다.
관련된 객체들의 집합을 생성하기 위한 인터페이스를 제공하여 새로운 객체를 추가할 때 해당 인터페이스를 구현하는 팩토리 클래스를 생성하는 방식입니다.
각 객체를 생성하는 메서드를 서브 클래스에서 오버라이드하여 유연성을 제공하게 되면, 새로운 객체를 추가할 때마다 기존의 팩토리 클래스를 변경할 필요 없이 새로운 팩토리 클래스를 추가하면 되는 방식입니다.