두번째로 '효과적인 자바' 를 보고 적는 포스트이다. 나중에 누군가(적어도 나)에게 도움이 되길 바란다.

자바, C++, C# 등의 객체지향 언어(물론 객체지향이 아니더라도)에는 생성자라는 함수(메소드와 혼용하겠다)가 존재한다.
항상 같은 형식의 new 클레스명(매개변수) 의 형식으로 사용되는 생성자 대신 static 로 선언되어있는 생성자를 만들어서 쓰자 라는 내용이다.

이런 static factory methode의 장점은 생성자가 무엇을 의미하는지 정확히 알려줄수 있다는 점이다.
예를들어 내가 이전에 만들었던 Matrix(행렬) 클레스를 예로 들어보자.
모든 값이 0인 행렬을 만들고 싶다 라고 한다면 이런형식의 생성자를 만들수 있을것이다.

public Matrix(int row, int col, int value);

Matrix zeros=new Matrix(10,10,0);

이런 형식의 생성자를 만든다면 한눈에 봤을 때 이것이 무엇을 의미하는지 알기가 힘들다.
물론 row와 col 은 행과 열의 크기 이겠지만 마지막의 value는 무엇인가?
본인은 기본적으로 행렬에 체우게 되는 값을 의미하려고 했지만 쉽게 와닫지는 않는다.

이 항목에서 조언해주는형식으로 바꾸어 보자.

private Matrix(int row, int col, int value);
public static Matrix zeros(int row, int col){
    return new Matrix(row, col, 0);
}
public static Matrix zeros(int size){
    return zeros(size, size);
}

물론 private Matrix(int row, int col, int value); 이것이 private 이될 이유는 없지만 보여줄 필요 없는것은 최대한 가린다는 캡슐화를 생각한다면 저렇게 하는것이 좋을수도 있다.

저렇게 두고본다면 zeros 라는 0행렬을 의미하는 팩토리 메소드는 누가 보더라도 row, col 크기의 0으로 체워진 행렬이겠구나 라는걸 쉽게 알아차릴수 있다.


두번째 장점은 생성자가 호출될때 매번 새로운 객체를 생성할 필요가 없다. 라는것이라고 한다.

디자인 패턴을 공부했다면 싱글톤이 무엇인지 알고 있을것 같다. 쉽게 말하면 그내용이다.
반드시 하나만 생성되어야 한다거나. 둘 이상이 생성될 필요가 없는 경우에 쓰면 유용하다는 것이다.
물론 이런경우에는 enum 이라는 좋은 물건이 있지만 경우에 따라 사용방법은 달라지는 것이다.

책에서 예로 들어놓은것은 boolean 의 랩퍼클레스(이렇게 적는게 맞나..;) Boolean 에 있는 valueOf 라는 메소드를 예로 들었다.
Boolean.valueOf(true/false) 라는 형식으로 호출하게 되면 true/false 값을 가지는 Boolean 클레스를 리턴 해주는데 이때 Boolean.TRUE와 Boolean.FALSE 를 항상 생성해서 넘겨주는 것이 아니라 레퍼런스만 넘겨주게 된다는 것이다. TRUE라는 값의 객체가 여러개 생성된다고 별 문제는 발생하지 않겠지만 그렇다고 쓸데없이 여러개 만들 이유가 없다는 것이다.


세번째 장점은 반환하는 클레스를 상속한 어떤 클레스라도 생성해서 넘겨줄수 있다. 라는것이다.
생성자는 자기 자신만 생성하는데 반해서 팩토리 메소드는 자신을 상속한 클레스도 넘겨 줄수 있는것이다.

잘된 예인지는 잘 모르겠지만 예전에 메세지 기반 통신을 프로그래밍 하면서 사용했던 방법이다.

abstract class Message{
    public static Message newInstance(String header){
        if("Send".equals(header){
            return new Send();
        }else{
            return new Control();
        }
    }
}

거의다 생략했지만 메세지의 header 에 따라서 생성되는 인스턴스는 Message를 상속한 Send 클레스나 Control 클레스가되는것이다.

부연설명을 하자면 Message에 있는 parse 메소드를 Send와 Control 에서 각각 구현한뒤 해더 뒤에 들어오는 내용들을 각각 다른 방법으로 파싱 했던것이다.

이런 객체 생성은 생성자로서는 구현하기가 어려울것이다.

이책에서 설명하는 마지막 장점은 매개변수화 타입인스턴스 생성을 간결하게 해준다. 라는것이다.
public static <K,V> HashMap<K,V> newInstance(){
    return new HashMap<K,V>();
}
이런 메소드를 생성하면
Map<Integer, String> m=HashMap.newInstance();
라고 쓸수 있다. 라고 하는데

자바 7에서 추가된 항목중에
new를 할때에는 제네릭 항목을 생략할수 있다. 라는것이다.
Map<Integer, String> m=new HashMap<>();
이라고 적어주면 된다.
물론 <> 이 들어가는것도 마음에 안든다면 어쩔수 없다.

여기까지 네가지 장점을 살펴봤는데 단점 도 있다!
첫번째 단점은 위에서 Matrix 를 예로 들면서 private 생성자를 만들었었는데. 저런식으로 해버리면 상속받은 클레스에서 super 생성자를 호출 할수가 없어진다는거다.

만약 Integer 만 가능한 Matrix 를 상속해서 Double도 가능하게 만들겠다. 라고 했는데 Matrix(int col, int row, int value) 가 private 로 선언되어 있다면 이건뭐 'ㅅ'...
-개떡같은 설명이지만 찰떡같이...

두번째 단점은 기타등등의 static 메소드랑 구별이 안된다. 라는것이다.
당연한 이야기다.
뭐 static factory methode 랑 기타등등이랑 구별하게 하려면 prefix(접두사)를 잘 붙이던지 뭐.. 재주껏 해야겠다.
물론 메모장이나 Editor+ 같은걸로 하는사람은 별 문제가 없다?! 라고 하지만 어차피 javadoc를 볼려먼 짜증나기는 매한가지


자주 사용되는 작명규칭
valueOf/of - 매개변수를 값으로 하는 객체를 리턴한다.
BigInteger 이나 Double 같은 클레스에서 잘 보인다.
getInstance - 싱글톤에서 자주 사용한다. 인스턴스가 유일하다는 의미라고 보면된다.
-getter, setter 에서 쓰는거랑 의미가 비슷하다. 물론 이놈들은 static가 아니지만!
newInstance - new 랑 똑같다?! (물론 똑같지는 않습니다..)


ps. 근데 이런거 쓰면 저작권 침해로 잡혀가나여..?
Posted by 동적할당
: