cf) 위키피디아 정의
- 특정한 계열의 알고리즘들을 정의하고
- 각 알고리즘을 캡슐화하며
- 이 알고리즘들을 해당 계열 안에서 상호 교체가 가능하게 만든다.
(source: https://ko.wikipedia.org/wiki/%EC%A0%84%EB%9E%B5_%ED%8C%A8%ED%84%B4)
Fly 인터페이스: 외부에서 동일한 방식으로 호출하여 해당 기능을 수행하게 함.
- Strategy: 인터페이스나 추상 클래스로 선언
WingFly, HandFly 클래스: Fly 인터페이스에서 명시한 기능을 구현한 클래스들.
Duck 클래스: 본인의 멤버, 참조변수를 통해 Strategy 패턴을 이용함.
필요에 따라 동적으로 구제척인 기능(전략)을 바꿀 수 있도록 setter 메서드 제공.
reference: https://gmlwjd9405.github.io/2018/07/06/strategy-pattern.html
로봇 클래스 활용과 OCP 원리 지키기
// 로봇 추상 클래스
public abstract class Robot {
private String name;
// 기능에 해당하는 참조변수
private AttackStrategy attackStrategy;
private MovingStrategy movingStrategy;
public Robot(String name){
this.name = name;
}
public String getName(){
return name;
}
// 추상 메서드
//public abstract void attack();
//public abstract void move();
// => 파생 클래스에 기능 구현을 맡기지 않는다.
// 생성 시 또는 별도의 설정 함수를 통해 설정되는 '행동' 객체를 통해 공격 또는 이동을 수행한다.
// 이를 통해 파생 클래스 구현 시 행동에 대한 추가 구현의 부담을 줄일 수 있다.
public void attack() { attackStrategy.attack(); }
public void move() { movingStrategy.move(); }
// 기능을 할당할 setter 메서드
// Robot클래스와 strategy 클래스 간의 관계는 '집약 관계', 로봇 객체가 메모리에서 사라진다 해도 strategy 객체는 사라지지 않음.
public void setAttackStrategy(AttackStrategy attackStrategy) {
this.attackStrategy = attackStrategy;
}
public void setMovingStrategy(MovingStrategy movingStrategy) {
this.movingStrategy = movingStrategy;
}
}
// 로봇 클래스를 상속받는 태권V 클래스
public class TaekwonV extends Robot {
public TaekwonV(String name){
super(name); // 부모 클래스의 매개변수 존재 생성자 활용
}
// 추상 메서드 구현(오버라이딩)
//public void attack(){
// System.out.println("I have Missile");
//}
//public void move(){
// System.out.pringln("I can only walk");
//}
// => 기능을 파생 클래스에서 구현하지 않는다.
}
// 로보 클래스를 상속받는 아톰 클래스
public class Atom extends Robot {
public Atom(String name){
super(name);
}
//public void attack(){
// System.out.println("I have strong punch");
//}
//public void move(){
// System.out.println("I can fly");
//}
// => 기능을 파생 클래스에서 구현하지 않는다.
}
// Attack strategy 인터페이스
interface AttackStrategy { public void attack(); }
// 구체적인 클래스
public class MissileStrategy implements AttackStrategy {
public void attack() { System.out.println("I have Missile."); }
}
public class PunchStrategy implements AttackStrategy {
public void attack() { System.out.println("I have strong punch."); }
}
// Moving strategy 인터페이스
interface MovingStrategy { public void move(); }
// 구체적인 클래스
public class FlyingStrategy implements MovingStrategy {
public void move() { System.out.println("I can fly."); }
}
public class WalkingStrategy implements MovingStrategy {
public void move() { System.out.println("I can only walk."); }
}
// 클라이언트에서의 사용
public class Client {
public static void main(String[] args) {
Robot taekwonV = new TaekwonV("TaekwonV");
Robot atom = new Atom("Atom");
/* 수정된 부분: 전략 변경 방법 */
// 각 구체 로봇 객체에 전략 종류에 맞는 기능(행위)를 주입한다.
taekwonV.setMovingStrategy(new WalkingStrategy());
taekwonV.setAttackStrategy(new MissileStrategy());
atom.setMovingStrategy(new FlyingStrategy());
atom.setAttackStrategy(new PunchStrategy());
/* 아래부터는 동일 */
System.out.println("My name is " + taekwonV.getName());
taekwonV.move();
taekwonV.attack();
System.out.println()
System.out.println("My name is " + atom.getName());
atom.move();
atom.attack();
}
}