정의

  • 알고리즘군(기능)을 정의하고 각각을 캡슐화하여 교환해서 사용할 수 있도록 한다.
  • 스트래티지 패턴을 사용하면 알고리즘을 사용하는 클라이언트와 독립적으로 알고리즘을 변경할 수 있다.

스트래티지 패턴의 적용 원칙

  • 자주 바뀌는 부분(기능)을 바뀌지 않는 부분과 분리하여 캡슐화 한다.
  • 상속 보다는 구성(멤버 변수?)을 활용한다.
  • 구현이 아닌 인터페이스에 맞추어 프로그래밍 한다.

원칙을 무시한 코드

/* 모든 게시판이 만들어질때 상속 받을 슈퍼 클래스 */
public class Article{
 public boolean insertArticle(){ 입력을 구현 }
 public List selectArticle(){ 선택을 구현 }
 public boolean updateArticle(){ 수정을 구현 }
}
/* Article을 상속 받은 SimpleArticle1 */
public class SimpleArticle1 extend Article{
 public List selectArticle(){선택을 구현}
}
/* Article을 상속 받은 SimpleArticle2 */
public class SimpleArticle2 extend Article{
 public List selectArticle(){선택을 구현}
}
  • 게시판에 삭제기능도 필요 하다는 요구조건이 추가되어 최상위 클래스인 Article에 삭제기능을 추가
/* 모든 게시판이 만들어질때 상속 받을 슈퍼 클래스 */
public class Article{
 public boolean insertArticle(){ 입력을 구현 }
 public List selectArticle(){ 선택을 구현 }
 public boolean updateArticle(){ 수정을 구현 }
 public boolean deleteArticle(){ 삭제를 구현 }
}
  • 이후 새로운 SimpleArticle3게시판을 추가했는데 해당 게시판은 글 삭제가 불가능한 게시판
/* Article을 상속 받은 SimpleArticle3 */
public class SimpleArticle3 extend Article{
 public List selectArticle(){선택을 구현}
 public boolean deleteArticle(){ 아무것도 하지 않도록 구현 }
}
  • 새로운 SimpleArticle4게시판을 추가했는데 해당 게시판은 글 쓰기,수정,삭제가 불가능한 게시판
/* Article을 상속 받은 SimpleArticle4 */
public class SimpleArticle4 extend Article{
 public boolean insertArticle(){ 아무것도 하지 않도록 구현 }
 public List selectArticle(){ 선택을 구현 }
 public boolean updateArticle(){ 아무것도 하지 않도록 구현 }
 public boolean deleteArticle(){ 아무것도 하지 않도록 구현 }
}

문제점

  • 선택 이외의 기능들은 자주 변경이 일어남.
  • Article에 구현되어 있는 기능을 상속을 받기 때문에 새로운 Article이 추가 될 때 마다 기능들을 새로 오버라이드 해야함

해결방법

  • 변경이 자주 일어나는 기능들을 때로 분리하여 캡슐화 한다.
  • 변경되는 기능을 Article에 구현이 아닌 구성을 사용한다.
  • 기능을 인터페이스화 하여 필요한 구현체를 게시판에서 선택하여 사용할 수 있게 한다.

원칙을 적용한 코드

/* Article에서 사용할 기능을 정의한 인터페이스 */
public interface ArticleDML{
 public boolean insertArticle();
 public boolean updateArticle();
 public boolean deleteArticle();
}
/* 삭제기능을 하지 못하는 Article에서 사용할 클래스 */
public class DoNotUseDeleteDML implements ArticleDML {
 public boolean insertArticle(){입력을 구현};
 public boolean updateArticle(){수정을 구현};
 public boolean deleteArticle(){아무것도 하지않음};
}
/* 입력,수정,삭제기능을 하지 못하는 Article에서 사용할 클래스 */
public class DoNotUseAllDML implements ArticleDML {
 public boolean insertArticle(){아무것도 하지않음};
 public boolean updateArticle(){아무것도 하지않음};
 public boolean deleteArticle(){아무것도 하지않음};
}
/* 모든 게시판이 만들어질때 상속 받을 슈퍼 클래스 */
public class Article{
 public ArticleDML articleDML; //Article에서 사용할 기능을 정의한 인터페이스
 public List selectArticle(){ 선택을 구현 } //모든 Article에서 변하지 않는 공통 기능
 public boolean insertArticle(){ articleDML.insertArticle() }
 public boolean updateArticle(){ articleDML.updateArticle() }
 public boolean deleteArticle(){ articleDML.deleteArticle() }
}
  • 삭제를 못하는 SimpleArticle3게시판의 변경
/* Article을 상속 받은 SimpleArticle3 */
public class SimpleArticle3 extend Article{
 public SimpleArticle3(){
  articleDML = new DoNotUseDeleteDML();
 }
 public List selectArticle(){선택을 구현}
}
  • 쓰기,수정,삭제가 불가능한 SimpleArticle4게시판의 변경
/* Article을 상속 받은 SimpleArticle4 */
public class SimpleArticle4 extend Article{
 public SimpleArticle3(){
  articleDML = new DoNotUseAllDML();
 }
 public List selectArticle(){ 선택을 구현 }
}

결과

  • 각 Article에 기능을 추가할때 선택 적용 할수 있게 됐다.
  • 구현 상속이 아닌 인터페이스 구성을 이용하여 기능의 변경에 좀더 간편 하게 적용할 수 있게 되었다.

이후에 더 변경할 부분을 찾아 보자