팩터리 메서드 패턴이란, 상위 클래스에는 객체를 생성하는 팩터리 메서드가 있고 하위 클래스에서 팩터리 메서드를 오버라이딩해서 객체를 반환하게 하는 것이다.
팩터리 메서드란 객체를 생성,반환하는 메서드이다.
따라서 팩터리 메서드 패턴은 이런 팩터리 메서드를 하위클래스에서 오버라이딩한 것을 의미한다.
상위 클래스는 하위 클래스에서 어떤 구체 클래스를 생성하는지 알지 모른다.
상위 클래스는 주로 인터페이스 타입으로 추상메서드를 만든다.
하위 클래스는 구체 클래스를 직접 생성한다.
객체 생성처리는 하위 클래스가 책임지기 때문에, 객체 생성의 변화 대비에 유용하다.
상위클래스나 인터페이스를 사용할 수 있다.
HandHygiene
package OOP06.factoryMethodPattern;
abstract public class HandHygiene {
void washingHands (){
step1();
step2();
System.out.println("손 문지르기");
}
//⭐⭐상위클래스에서 추상메서드로 객체 반환⭐⭐
abstract handHygieneProducts getProducts();
void step1(){
System.out.println("물 묻히기");
}
abstract void step2();
}
package OOP06.factoryMethodPattern;
public class HandHygien_Soap extends HandHygiene {
@Override
//⭐⭐하위클래스에서 추상메서드 오버라이딩해 객체 반환⭐⭐
handHygieneProducts getProducts() {
return new soap();
}
@Override
void step2() {
System.out.println("비누 사용");
}
}
package OOP06.factoryMethodPattern;
public class HandHygien_Sanitizer extends HandHygiene {
@Override
handHygieneProducts getProducts() {
return new sanitizer();
}
@Override
void step1() {
System.out.println("물없이");
}
@Override
void step2() {
System.out.println("소독제 사용");
}
}
handHygieneProducts
인터페이스와 하위 구현 클래스package OOP06.factoryMethodPattern;
public interface handHygieneProducts {
abstract void use();
}
package OOP06.factoryMethodPattern;
public class sanitizer implements handHygieneProducts{
@Override
public void use() {
System.out.println("소독제 사용");
}
}
package OOP06.factoryMethodPattern;
public class soap implements handHygieneProducts{
@Override
public void use() {
System.out.println("비누 사용 🫧");
}
}
package OOP06.factoryMethodPattern;
public class Driver {
public static void main(String[] args) {
HandHygiene useSanitizer = new HandHygien_Sanitizer();
HandHygiene useSoap = new HandHygien_Soap();
useSoap.washingHands();
useSanitizer.washingHands();
handHygieneProducts sanitizer = useSanitizer.getProducts();
handHygieneProducts soap = useSoap.getProducts();
sanitizer.use();
soap.use();
}
}
실행화면
물 묻히기
비누 사용
손 문지르기
물없이
소독제 사용
손 문지르기
소독제 사용
비누 사용 🫧
클래스의 결합도를 낮출 수 있다.
팩토리 메서드 패턴을 사용하여 직접 객체를 생성해서 사용하지 않고, 하위 클래스에 위임함으로써 의존성을 제거할 수 있다.
객체를 생성하는 부분은 빈번한 변경이 일어날 수 있다.
따라서 객체 생성 역할을 따로 두면서 변화에 둔감하도록 결합도를 낮추는 것이다.
클래스의 결합도란,
클래스의 변경점이 생겼을 때 얼마나 다른 클래스에도 영향을 주는가이다.
HandHygiene 클래스의 handHygieneProducts getProducts()
상위 클래스에서 추상 메서드로 선언되어 있으며, 하위 클래스에서 구현되어 하위 클래스가 어떤 구체적인 제품을 생성할지 결정하도록 되어 있습니다.
handHygieneProducts getProducts()
하위 클래스에서는 상위 클래스의 추상 메서드를 오버라이딩하여 구체적인 제품을 생성하도록 구현하고 있습니다.
이 부분에서 상위 클래스(HandHygiene)가 추상화된 인터페이스를 통해 하위 클래스에 의존하고 있으며, 실제로 어떤 구현이 사용될지는 하위 클래스에서 결정되기 때문에 의존 역전 원칙이 적용되었다고 볼 수 있습니다.
의존 역전 원칙 : 구체적인 것이 추상적인 것에 의존하다.
즉, 더 자주 변경되는 것,구체적인 것이 덜 자주 변경되는 것,추상화된 것에 의존해야한다.
위 코드에서는 자주 변경되는 객체 생성 부분이 하위클래스에서 구현되고, 상위클래스는 인터페이스와 추상메서드를 사용하면서, 의존하지 않는다. 다시 말해서 어떤 객체가 실제로 생성되는지 알지 않아도 된다.
객체 생성 부분은 자주 변경되기 때문에 구체적인 하위클래스에서 생성하고있다. (의존하고있다?!)
하위 클래스의 역할은 탬플릿메서드의 구현을 완성하는 것으로 생각했다. 그래서 이 코드가 단일책임원칙을 적용하고 있는지는 사실 모르겠다. 객체 생성을 위해서 계속 하위클래스를 수정해야하니까... 하지만 탬플릿 메서드를 위해 짠 코드니 어느정도 ...는... 허용으로ㅎ;;
코드를 짜다보면 여러 객체를 생성하고, 사용하게 될 것이다.
그런데 이 객체를 생성하는 부분은 자주 변경될 것이다.
따라서 별도의 구체적인 객체 생성 공장을 만드는 것이 좋다.
스프링에서는 이를 위해서 어떤 것을 마련했을까?