: 마커 인터페이스는 메서드 선언이 없는 인터페이스이다. 대표적인 마커 인터페이스로 Serializable과 Cloneable이 있다. 마커 인터페이스를 활용하는 예를 살펴보자.
ex) 복잡한 조건문이 필요한 로직
if(A||B){ operationA(); } if(A||B||C){ operationB(); } if(C||D||E){ operationC(); } if(B||D||E){ operationD(); }
복잡한 조건문이 필요한 로직을 구현할 때 위와 같이 구현할 것이다. 하지만 조건이나 해야할 작업(operationX)이 추가된다면 코드를 수정하는 데 번거롭다. 또한 기존 로직을 모르는 사람이 코드를 건드려야 한다면 어려움이 많을 것이다. 대안으로 상속을 통해서 복잡도를 해결할 수는 있다. 부모 클래스에서 operationX()를 구현한 다음 조건 별로 자식 클래스를 만들어서 operationX를 호출하거나 오버라이드할 수 있다. 복잡도는 어느 정도 해결되지만 문제가 있다. 여러 작업을 할 때 메서드 호출 순서가 중요한데 순서를 잘못 호출 가능성이 있다. 또한 자식 클래스에서 여러 개의 operationX()를 호출하는 데 이 들 중 하나를 사용하지 않게 될 경우 주석처리를 한다. 이는 소스가 지저분해질 수 있고 주석 해제 과정에서 실수할 가능성도 있다. 또 조건을 추가할 때 자식 클래스 중에서 비슷한 operationX을 사용해 해당 자식 클래스를 상속해서 구현할 수 있다. 상속을 많이 하게 되면 코드 수정시 바뀔 부분이 많기 때문에 상속을 최소화 하는 게 좋다. 이러한 문제들을 해결해 주는 게 마커 인터페이스이다. 다음은 마커 인터페이스로 복잡한 조건문을 단순화시키는 방법이다.
1. 각 작업을 마커 인터페이스로 매핑한다.
public interface Markable1{} public interface Markable2{} public interface Markable3{} public interface Markable4{}
2. 각 조건별로 자식 클래스를 만든다.
AClass extends Category implements Markable1, Markable2 {} BClass extends Category implements Markable1, Markable4 {} CClass extends Category implements Markable2, Markable3 {} DClass extends Category implements Markable3, Markable4 {}
if(this instanceof Markable1){ operationA(); } if(this instanceof Markable2){ operationB(); } if(this instanceof Markable3){ operationC(); } if(this instanceof Markable4){ operationD(); }
위와 같이 마커 인터페이스를 활용하면 먼저 부모 클래스에서 operationX()의 순서가 정해져 작업 순서가 바뀔 경우가 줄어든다. 또한 특정 oprerationX를 호출해야 하지 않아야 할 때 imprements 만 빼면 된다. operationX를 추가할 때도 인터페이스만 추가하면 된다.
마커 인터페이스는 마커 어노테이션(Annotation)으로 활용 가능하다. 위 마커 인터페이스 예를 마커 어노테이션으로 바꿔보자.
@Retention(RetentionPolicy.RUNTIME) @interface Markable1{ } @Retention(RetentionPolicy.RUNTIME) @interface Markable2{ } @Retention(RetentionPolicy.RUNTIME) @interface Markable3{ } @Retention(RetentionPolicy.RUNTIME) @interface Markable4{ }
Class clazz = this.getClass(); if(clazz.isAnnotationPresent(Markable1.class)){ operationA(); } if(clazz.isAnnotationPresent(Markable2.class)){ operationB(); } if(clazz.isAnnotationPresent(Markable3.class)){ operationC(); } if(clazz.isAnnotationPresent(Markable4.class)){ operationD(); }
마커 인터페이스나 마커 어노테이션이나 별반 차이가 없어 보인다. 하지만 인터페이스는 자식 클래스에도 영향을 미치지만 어노테이션은 자식 클래스에 영향을 안 미친다. 상황에 맞게 사용하면 될 것 같다.
'안드로이드 > 기본' 카테고리의 다른 글
SQLite 주의할 점 및 팁 - DB LOCK(락), SQLiteOpenHelper (2) | 2017.08.05 |
---|---|
안드로이드 커스텀 뷰 만들기 (2) | 2017.08.03 |
안드로이드 태스크, launchMode, Intent 플래그 총정리 (0) | 2017.08.03 |
안드로이드 슬립 상태 대처하기 (0) | 2017.08.02 |
안드로이드 액티비티(Activity) 생명주기 총정리 (0) | 2017.08.02 |