본문 바로가기
Effective JAVA 2판

Effective JAVA Item21 전략을 표현하고 싶을 때는 함수 객체를 사용하라

by BroBroBro 2015. 7. 8.

------------------------------------------------

본글은 Effective JAVA 2판의 책의 내용을 토대로 작성하였으며
지극히 주관적인 사항들이 많이 있으므로 가려서 읽으시기바랍니다.
잘못된 내용이 있거나 의견이 있으시다면 언제든 댓글로^^~!

------------------------------------------------

CHAPTER 4 클래스와 인터페이스

4장에서는 클래스와 인터페이스를 설계할때 이용할 수 있는 강력한 요소들을 많이 갖추고 있다고 한다. 

[Item 13] 클래스와 그 멤버의 접근 권한을 최소화하자 부터 보도록 하자 

Item14 public 클래스 안에는 public 필드를 두지말고 접근자(accessor) 메소드를 사용한라
Item15 변경 기능성을 최소화 하라 
Item16 계승하는 대신 구성하라
Item17 계승을 위한 설계와 문서를 갖추거나, 그럴 수 없다면 계승을 금지하라
Item18 추상 클래스 대신 인터페이스를 사용하라
Item19 인터페이스는 자료형을 정의할 때만 사용하라
Item20 태그 달린 클래스 대신 클래스 계층을 활용하라
Item21 전략을 표현하고 싶을 때는 함수 객체를 사용하라
Item22 멤버 클래스는 가능하면 static으로 선언하라.

--page01

본장에서는 객체 참조를 통한 함수전달을 말하고있다.
이것은 전략패턴과 동일하다.

보통은 이런식으로 사용할수있을것이다.

1
2
3
4
5
class StringLengthComparator{
    public int compare(String s1, String s2){
      return s1.length() - s2.length();
   }
}
cs

첫번째인자가 길면 양수
두번째인자가 길면 음수
같으면 0을 반환

StringLengthComparator 이놈이 바로 함수 포인터 구실을 하는것이다.

실행 가능 전략클래스들은 대체로 무상태(stateless)클래스라고 한다. 이놈도 마찬가지이다.

쓸데없는 객체의 생성을 피하기 위해서 아래와 같이 만들수있겠다.

1
2
3
4
5
6
7
class StringLengthComparator{
   private StringLengthComparator() {}
   public static final StringLengthComparator INSTANCE = new StringLengthComparator();
    public int compare(String s1, String s2){
      return s1.length() - s2.length();
   }
}
cs

여기서 한걸음 더나가보면 StringLengthComparator외에 IntLengthComparator ?? 이런것도 있을수 있다.

자료형을 맞추기 위해서 규약을 강제해보자. 아래와 같을 것이다.

1
2
3
4
5
6
7
8
9
10
11
public interface Comparator<T>{
   public int compare(T t1, T t2);
}
 
class StringLengthComparator implements Comparator<String>{
   private StringLengthComparator() {}
   public static final StringLengthComparator INSTANCE = new StringLengthComparator();
    public int compare(String s1, String s2){
      return s1.length() - s2.length();
   }
}
cs

위예제에서 나오는 T는 formal type parameter 라고 부른다.

아래와 같은 곳에서 사용한다고 해보자.
1
2
3
4
5
Arrays.sort(stringArray, new Comparator<String>(){
    public int compare(String s1, String s2){
      return s1.length() - s2.length();
   }
}
cs

익명클래스이다. 하지만 호출될때마다 새로운 객체를 생성하는 단점이 있다. 
즉 딱한번 사용할시에는 위와 같은 방법이 좋다.
여러번사용할경우는 아래와 같이 사용하면 된다.
익명클래스 대신 static멤버 클래스를 사용하고있다.

1
2
3
4
5
6
7
8
9
10
Class Host{
   private static class StrLenCmp implements Comparator<String>, Serializable{
      public int compare(String s1, String s2){
         return s1.length() - s2.length();
      }
   }
 
   public static final Comparator<String> STRING_LENGTH_COMPARATOR = new StrLenCmp();
   ...
}
cs


실제 String Class에서는 아래와 같은 사용예가 있습니다.
   Collections.sort(list, String.CASE_INSENSITIVE_ORDER);

우리가 뭘배우고 있었죠? ㅋ  전략을 표현하고 싶을때는 함수객체를 이용하자고 합니다. 
이상 지금까지 함수객체의 사용이였습니다.