안드로이드 NFC 예제를 보면서 괜찮은 기법이 있어서 소개할까합니다. (저만 몰랐던 걸 수도 있구요. :D ) 

제가 본 소스의 일부를 쓰자면

BiMap<Byte, String> URI_PREFIX = BiMap.<Byte, String>builder()
            .put((byte) 0x00, "")
            .put((byte) 0x01, "http://www.")
            .put((byte) 0x02, "https://www.")
            .put((byte) 0x03, "http://")
            .put((byte) 0x04, "https://")
            .put((byte) 0x05, "tel:")
            .build();



맵에 요소를 넣으면서 URI_PREFIX에 인스턴스를 할당하는 구문입니다. 

처음 봤을 때는 저게 원래 자바에서 지원하는 문법인가 싶어서  객체 안에 있는 메서드
위처럼 세미콜론 없이 닷만 찍어서 계속 해보려했는데 당연히도 에러가 나더군요. 

위 문장을 보고 저게 뭐? 라고 생각하셨다면 아래에 쓰는 체이닝 기법을 적용하지 않고 작성한 소스를 보고 비교해보세요.

BiMap<Byte, String> URI_PREFIX =
BiMap.<Byte, String>builder().build(); 
URI_PREFIX.put((byte) 0x00, "");
URI_PREFIX.put((byte) 0x01, "http://www.");
URI_PREFIX.put((byte) 0x02, "https://www.");
URI_PREFIX.put((byte) 0x03, "http://");
URI_PREFIX.put((byte) 0x04, "https://");
URI_PREFIX.put((byte) 0x05, "tel:"); 


개인적인 차이일지도 모르겠지만 저는 체이닝 기법을 적용한 소스가 더 깔끔하고 직관적으로 느껴지네요. 서론은 여기까지 하고 실제로 어떻게 체이닝 기법을 적용할 수 있는지 예제를 만들면서 알아봅시다.

만들 클래스는 간단한 학생 정보 클래스입니다. 체이닝 기법을 적용한다고 해서 그리 효율적인 클래스가 되진 않겠지만 간단한 예를 위해서 이 클래스를 씁니다.

/** 학생정보 클래스 */
class Student{
private String name; // 학생이름
private String number; // 학번
private int birthyear; // 생년
private String dept; // 학과 

public void setName(String name){
this.name = name;
}

public void setNumber(String number){
this.number = number;
}

public void setBirthyear(int birthyear){
this.age = age;
}

public void setDept(String dept){
this.dept = dept;
}

/* getter 생략 */ 
}



위 클래스에서 생성자를 두지 않는다고 가정하면 학생 인스턴스에 정보를 넣기위해서는 아래와 같이 코드를 작성하게 되겠죠

Student student = new Student();
student.setName("세종대왕");
student.setNumber("7284910");
student.setBirthyear(1397);
student.setDept("국어국문학과");



체이닝 기법을 적용하기 위해서 뮤테이터(세터) 메서드의 반환형을 void에서 오브젝트를 반환하도록 Student 타입으로 바꿔 줍니다.
그리고 메서드 구현부의 끝에 return this;를 써서 객체를 반환하도록 하구요.
DSL에서는 setName과 같은 메서드 이름도 더 직관적으로 바꾸지만 익숙함을 위해서 그대로 쓰도록 하겠습니다. 위의 Student 클래스를 체이닝 기법을 적용하기 위한 소스로 바꿔보면 아래와 같습니다. 빨간색 글씨가 수정된 부분입니다

/** 학생정보 클래스 */
class Student{
private String name; // 학생이름
private String number; // 학번
private int birthyear; // 생년
private String dept; // 학과 

public Student setName(String name){
this.name = name;
return this;
}

public Student setNumber(String number){
this.number = number;
return this;
}

public Student setBirthyear(int birthyear){
this.age = age;
return this;
}

public Student setDept(String dept){
this.dept = dept;
return this;
}

/* getter 생략 */ 
}



클래스를 바꿨으니 인스턴스를 할당할 때도 바로 적용해 봅시다.

Student student = new Student()
.setName("세종대왕")
.setNumber("7284910")
.setBirthyear(1397)
.setDept("국어국문학과");



네. 이상입니다.
원리는 간단합니다. 계속해서 객체를 반환하니 메서드를 다시 호출해서 쓸 수 있고. 역시 student 변수는 Student 클래스 타입이니 반환한 객체 그대로 받을 수 있게 됩니다.  

'밤을 지새다 > Java' 카테고리의 다른 글

Java StAX: XMLInputFactory  (0) 2012.04.30
Java StAX  (0) 2012.04.30
Exceptions  (0) 2011.09.05
자바. 얼마나 알고 사용하고 계신가요?  (0) 2011.08.25
객체를 바이트 배열로, 바이트 배열을 객체로  (0) 2011.08.22

+ Recent posts