학습 목표
- 장점과 단점을 이해 하는 것이 목표입니다.
장점
🔴 이름을 가질 수 있다.
생성자에서 제공하는 파라미터가 주입을 받을 시점에 무슨 의미인 데이터인지 클라이언트에서는 알기가 어려운 부분이 있는데 이때 우리는 정적 팩토리 메서드를 고려해 볼 만합니다.
person 이라는 클래스에 name 과 nickName 을 정의 하고 생성자를 만듭니다.
객체를 생성하여 파라미터를 받아봅시다.
스폰지밥과 스폰지가 파라미터로 받아오는데 어떤 의미가 있는지 명확하게 알 수 가 없다.
이때 사용하는 것이 정적 팩토리 메서드이다.
정적 팩토리 메서드는 이름을 가질 수 있고 그 이름으로 의미상 추론을 할 수 있다.
이 메시지는 이름을 원하다라는 의미를 갖고있다.
person 이라는 객체를 생성 후 파라미터를 받을 때 우리는 정적 팩토리 메서드를 사용하여 의미상 추론을 할 수 있게 해주고 보는 입장에서도 보기 쉽게 설명이 된다.
동일한 시그니처를 받는 생성자는 중복으로 생성이 안된다.
동일한 타입으로 받는 파라미터를 생성하는 생성자는 중복으로 생성이 안된다.
address와 email을 새로 받아 생성자를 생성해보면 이전에 생성했던 생성자와 동일 타입이여서 컴파일 에러가 뜨는 것을 볼 수 있다.
여기서도 정적 팩토리 메서드를 사용하면 동일 시그니처 생성도 가능하다.
불가능 했던 동일 시그니처가 생성이 가능해졌다.
🔴 반드시 새로운 객체를 만들 필요가 없다.
객체를 매번 생성할 필요가 없이 정적으로 미리 만들어 놓고 사용할 수도 있다.
매번 새로운 객체를 만들지않고 한번만 객체를 만들어 반환하는 정적 팩토리 메서드를 사용 해보았다.
🔴 리턴 타입의 하위 타입 인스턴스를 만들 수도 있다.
반환 타입을 구체로 하고 실제 반환 하는 객체는 구현체로 반환한다.
객체지향의 특징인 다형성과 캡슐화를 살펴보겠다.
다형성은 서로 관계가 있는 클래스들의 여러 타입으로 변환 할 수 있다.
캡슐화는 내부 로직은 숨기고 식별자를 통해 접근을 해야한다.
즉, 메서드 이름과 타입만으로 접근을 한다는 말이다.
Collection 을 다루고 인터페이스 역할을 하는 Collections 클래스가 예를 들을 수 있다.
java.util.Collections 와 같은 정적 팩토리 메서드 기반인 인터페이스들을 사용하면 코드의 유연성을 제공해 줄 수 있다.
🔴 리턴하는 객체의 클래스가 입력 매개변수에 따라 매번 다를 수 있다.
세번째 장점과 같이 다형성을 제공해주는 것을 말한다.
입력 매개변수를 받아 반드시 반환 구체인 것을 반환 할 필요는 없다.
이처럼 정적 팩토리 메서드를 사용하여 이름을 가질 수 있는 장점과 타입의 유연성을 제공해주는 다형성의 특징으로 입력 매개 변수에 따라 리턴해주는 인스턴스가 달라질 수 있다.
🔴 리턴하는 객체의 클래스가 public static 팩토리 메서드를 작성할 시점에 반드시 존재하지 않아도 된다.
정적 팩토리 메서드는 service provider framework 의 근본이다.
jdbc를 사용할 때 drivermanager를 사용한다.
drivermanger.registerDriver() 는 서비스를 제공해준다.
drivermanger.connection() 은 데이터베이스에 연결 시켜 서비스에 접근을 한다.
driver 는 서비스의 인터페이스 역할을 한다.
참조 : https://velog.io/@jihoson94/Service-Provider-Framework-Interface
provider service 기반이 아닌 경우에는 reflection을 사용하여 해당 클래스의 관계가 있는 클래스를 접근하여 리턴값으로 설정 할 수 있다.
store 클래스의 풀패키지명을 알고 있을 때의 예제 코드이다.
store 클래스의 풀패키지명은 com.company.effectivejava.Store 이다.
Class.forName() 메서드를 사용하여 파라미터 값으로 풀패키지명을 넣어준다.
여기서 해당 풀패키지에 클래스가 없을 경우 ClassNotFoundException 예외가 발생되므로 try catch 로 예외처리를 할 수 있고, 해당 메서드 명에 예외를 던질 수도 있다.
찾아온 클래스에 생성자 정보를 입력해주고 getConstructor() 메서드로 생성자 정보를 얻어와 파라미터 타입의 정보를 제공해준 다음 newInstance() 메서드로 파라미터 값을 넣어 인스턴스를 생성해준다.
다음 NoSuchMethodException,. InvoationTargetException, InstantiationException 클래스의 대한 예외 처리를 해준다.
반환 타입은 상위 클래스인 Book 이 되는데 down casting을 하여 Store라는 인스턴스를 얻을 수 있다.
단점
😡 public 또는 protected 생성자 없이 static 메서드만 제공하는 클래스는 상속할 수 없다.
Collections 라는 인터페이스 기반으로 전략을 짠 클래스인데 굳이 상속을 할 필요가 없다. 단점이라 말할 수도 있고 장점이라 말할 수도 있겠다.
😡 코드를 사용하는 사용자가 static 팩토리 메서드를 찾는게 어렵다.
생성자처럼 api 설명에 명확히 드러나지 않아 사용자는 api 문서를 잘 작성해야하고 메서드 이름도 명명규칙을 따라서 작성해야한다.
명명규칙
- from : 매개변수 하나를 받아서 해당 타입의 인스턴스를 반환하는 형변환 메서드
- of : 매개변수 여러개를 받아서 적합한 타입의 인스턴스를 반환하는 집계 메서드valueOf : from과 of의 더 자세한 버전instance or getInstance : 동일한 인스턴스를 반환하는 메서드
- create or newInstance : 새로운 인스턴스를 반환하는 메서드getType : getInstance와 같으나, 해당 클래스의 타입이 아닌 정의한 타입을 반환하는 메서드newType : newInstance와 같으나, 해당 클래스의 타입이 아닌 정의한 타입을 반환하는 메서드
- type : getType과 newType의 간결한 버전
'Book > Effective Java' 카테고리의 다른 글
[Book] ITEM 9) try-finally 대신 try-with-resource 를 사용하라 (0) | 2022.03.19 |
---|---|
[Book] ITEM 8) finalizer 와 cleaner는 피하라 (0) | 2022.03.07 |
[Book] ITEM 7) 더이상 쓰지 않는 객체 레퍼런스는 없애자 (0) | 2022.03.04 |
[Book] ITEM 6) 불필요한 객체는 만들지 말자 (0) | 2022.03.03 |
[Book] ITEM 5) 리소스를 엮을 때는 의존성 주입을 선호하라 (0) | 2022.03.03 |
[Book] ITEM 4) private 생성자로 noninstantiability를 강제할 것 (0) | 2022.03.01 |
[Book] ITEM 3) private 생성자 또는 enum 타입을 사용해서 싱글톤으로 만들것 (0) | 2022.03.01 |
[Book] ITEM 2) 생성자의 매개변수가 많다면 빌더를 고려하라 (0) | 2022.02.26 |