Effective Java 2|E <객체의 생성과 삭제-static method&생성자>

DoItDev·2021년 8월 1일
0
post-thumbnail

규칙1: 생성자 대신에 정적 팩터리 메서드를 사용할 수 없는 지 생각해 보라

public static Boolean valueOf(boolean b){
	return b ? Boolean.True : Boolean.False;
 }
  1. 정적 팩터리 메서드는 이름이 있다.
    생상자는 이름이 없다.
    생성자를 마구자비식으로 만든다면 코드적으로 클린하지 못하며 기능에 대한 정의가 어렵다.
    생성자 오버라이드 해서 사용시 인자만 바꾸어서 사용하는데 그렇게 하면 용도를 절때 기억하지 못한다.
  1. 생성자와는 달리 호출할 때마다 새로운 객체를 생성할 필요는 없다.
    같은 객체가 불필요하게 사용되거나 하는 일이 없다.
    경량 패턴과 유사하다.
    개체 통제 클래스 (instance-controlled class) 라고 한다.
  • 개체 수를 제어하면 싱글턴 패턴을 따르도록 할 수 있다.
  • 객체 생성이 불가능한 클래스를 만들수 도 있다.
  • 변경이 불가능한 클래스의 경우 두개의 같은 객체가 존재하지 못하도록 할수도 있다.
    ex) equals 메소드
  1. 생성자와는 달리 반환값 자료형의 하위 자료형 객체를 반환할 수 있다.
    유연하게 사용이 가능하다.

서비스 제공자 프레임워크

  • 서비스 인터페이스 : 서비스 제공자가 구현
  • 제공자 등록 api : 구현체를 시스템에 등록하여 클라이언트가 쓸 수 있도록한다.
  • 서비스 접근 api : 클라이언트에게 실제 서비스 구현체를 제공
  • 서비스 제공자 인터페이스: 옵션사항이며 서비스 제공자가 구현한다. 서비스 구현체의 객체를 생상하기 위한 것이다.
//서비스 제공자 인터페이스의 대략적인 모습

//서비스 인터페이스
public interface Service{
... // 서비스의 고유한 메소드
}

//서비스 제공자 인터페이스
public interface Provider{
Service newService();
}

//서비스 등록과 접근에 사용되는 객체 생성 불가능 클래스
public class Service {
	
    private Service(){}
    
    //서비스 이름과 서비스 간 대응 관계 보관
    private static final Map<String, Provider> providers = new ConcurrentHashMap<String, Provider>();
    public static final String DEFAULT_PROVIDER_NAME = "<def>";
    
    //제공자 등록 api
    public statics void registerDefaultProvider(Provider p){
    	registerProvider(DEFAULT_PROVIDER_NAME, p);
    }
    public static void registerProvider(String name, Provider p){
    	providers.put(name, p);
    }
    
    // 서비스 접근 api
    public static Service newInstance(){
    	return newInstacne(DEFAULT_PROVIDER_NAME);
    }
	public static Service newInstance(String name){
    	Provider p = providers.get(name);
        if(p == null) throw new Exception("no provider name :: " + name);
    	return p.newService();
    }
}
  1. 형인자 자료형 객체를 만들때 편리하다.

public static <K, V> HasMap<K, V> newInstance(){
	return new HasMap<K,V>();
}

// 간결해 졌다
Map<String,List<String>> m = HashMap.newInstace();

단점

정적 팩터리 메서드만 있는 클래스를 만드련 생기는 가장 큰 문제는 public, protected 로 선언된 생성자가 없으므로 하위 클래스를 만들 수 없다.

  • 개승 보다는 구성 기법을 쓰기위한 장려하는 이유이다.
    ex) Collection 객체

정적 팩터리 메서드가 다른 정적 메서드와 확연히 구분되지 않는다는 것이다.

  • 생성자 대신 정적팩터리 메서드를 통해 객체를 만들어야하는 클래스는 사용방법을 파악하기 쉽지않는다.
  • 이름을 명확히 지어주거나 주석을 통해 작성을 해야된다.

보통의 정적 팩터리 메서드 이름

  • valueOf: 인자로 주어진 값과 같은 값을 갖는 객체를 반환한다는 의미 (형변환 메서드)
  • of: valueOf를 간단하게 쓴것이다.
  • getInstance: 인자에 기술된 객체를 반환 하지만 인자와 같은 값을 가지지 않을수 있다.
    싱글턴 패턴의 경우 인자 없이 항상 같은 값을 반환
  • newInstance: getInstance 와 같지만 호출시 다른 객체를 반환
  • getType: getInstance 와 같지만 반환될 객체의 클래스와 다른 클래스에 팩터리 메서드가 있을 때 사용.
    type 은 팩터리 메서드가 반환할 객체의 자료형
  • newType: newInstance 와 같지만 반활될 객체의 클래스와 다른 클래스에 팩터리 메서드가 있을때 사용.

요약

정적 팩터리 메서드와 public 생성자는 용도가 서로 다르다
정적 팩터리 메서드가 효가적인 경우가 많으니, 정적 패터리 메서드를 고래해 보고 도저히 안된다 싶을때
public 생성자를 사용하는 부분은 왠만하면 선호하면 안된다.
나도 이부분에 있어서 동의하는 바이다 ... 현업에서 사용을 해보았는데 상당히 안좋은 습관인거 같다.

about

Effective Java 2/E

profile
Back-End Engineer

0개의 댓글