μ λ΅ ν¨ν΄ ( Strategy Pattern )
κ°μ²΄λ€μ΄ ν μ μλ νμ κ°κ°μ λν΄ μ λ΅ ν΄λμ€λ₯Ό μμ±νκ³ , μ μ¬ν νμλ€μ μΊ‘μν νλ μΈν°νμ΄μ€λ₯Ό μ μνμ¬,
κ°μ²΄μ νμλ₯Ό λμ μΌλ‘ λ°κΎΈκ³ μΆμ κ²½μ° μ§μ νμλ₯Ό μμ νμ§ μκ³ μ λ΅μ λ°κΏμ£ΌκΈ°λ§ ν¨μΌλ‘μ¨ νμλ₯Ό μ μ°νκ² νμ₯νλ λ°©λ²μ λ§ν©λλ€.
κ°λ¨ν λ§ν΄μ κ°μ²΄κ° ν μ μλ νμλ€ κ°κ°μ μ λ΅μΌλ‘ λ§λ€μ΄ λκ³ , λμ μΌλ‘ νμμ μμ μ΄ νμν κ²½μ° μ λ΅μ λ°κΎΈλ κ²λ§μΌλ‘ νμμ μμ μ΄ κ°λ₯νλλ‘ λ§λ ν¨ν΄μ λλ€.
1. μ λ΅ ν¨ν΄ μ¬μ© μ΄μ
μλ₯Ό λ€μ΄, κΈ°μ°¨( Train )μ λ²μ€( Bus ) ν΄λμ€κ° μκ³ , μ΄ λ ν΄λμ€λ Movable μΈν°νμ΄μ€λ₯Ό ꡬννλ€κ³ κ°μ νκ² μ΅λλ€.
κ·Έλ¦¬κ³ Trainκ³Ό Bus κ°μ²΄λ₯Ό μ¬μ©νλ Clientλ μμ΅λλ€.
μ΄ κ΅¬μ‘°λ₯Ό μ½λλ‘ νννλ©΄ λ€μκ³Ό κ°μ΅λλ€.
public interface Movable {
public void move();
}
public class Train implements Movable{
public void move(){
System.out.println("μ λ‘λ₯Ό ν΅ν΄ μ΄λ");
}
}
public class Bus implements Movable{
public void move(){
System.out.println("λλ‘λ₯Ό ν΅ν΄ μ΄λ");
}
}
public classClient {
public static void main(String[] args){
Movable train =newTrain();
Movable bus =newBus();
train.move();
bus.move();
}
}
κΈ°μ°¨λ μ λ‘λ₯Ό λ°λΌ μ΄λνκ³ , λ²μ€λ λλ‘λ₯Ό λ°λΌ μ΄λν©λλ€.
κ·Έλ¬λ€ μκ°μ΄ νλ¬ μ λ‘λ₯Ό λ°λΌ μμ§μ΄λ λ²μ€κ° κ°λ°λμλ€κ³ κ°μ ν΄λ΄ μλ€.
κ·Έλ¬λ©΄ Busμ move() λ©μλλ₯Ό λ€μκ³Ό κ°μ΄ λ°κΏμ£ΌκΈ°λ©΄ νλ©΄ λλ©λλ€.
public void move(){
System.out.println("μ λ‘λ₯Ό λ°λΌ μ΄λ");
}
κ·Έλ°λ° μ΄λ κ² μμ νλ λ°©μμ SOLIDμ μμΉ μ€ OCP( Open-Closed Principle )μ μλ°°λ©λλ€.
OCPμ μνλ©΄ κΈ°μ‘΄μ move()λ₯Ό μμ νμ§ μμΌλ©΄μ νμκ° μμ λμ΄μΌ νμ§λ§, μ§κΈμ Busμ move() λ©μλλ₯Ό μ§μ μμ νμ§μ.
λν μ§κΈκ³Ό κ°μ λ°©μμ λ³κ²½μ μμ€ν μ΄ νμ₯μ΄ λμμ λ μ μ§λ³΄μλ₯Ό μ΄λ ΅κ² ν©λλ€.
μλ₯Ό λ€μ΄, λ²μ€μ κ°μ΄ λλ‘λ₯Ό λ°λΌ μμ§μ΄λ νμ, μκ°μ©, κ³ μλ²μ€, μ€ν λ°μ΄ λ±μ΄ μΆκ°λλ€κ³ ν λ, λͺ¨λ λ²μ€μ κ°μ΄ move() λ©μλλ₯Ό μ¬μ©ν©λλ€.
λ§μ½μ μλ‘ κ°λ°λ μ λ‘λ₯Ό λ°λΌ μμ§μ΄λ λ²μ€μ κ°μ΄, μ λ‘λ₯Ό λ°λΌ μμ§μ΄λ νμ, μκ°μ©, κ³ μλ²μ€ ... λ±μ΄ μκΈ΄λ€λ©΄,
νμ, μκ°μ©, κ³ μλ²μ€μ move() λ©μλλ₯Ό μΌμΌμ΄ μμ ν΄μΌ ν λΏλλ¬, κ°μ λ©μλλ₯Ό μ¬λ¬ ν΄λμ€μμ λκ°μ΄ μ μνκ³ μμΌλ―λ‘ λ©μλμ μ€λ³΅μ΄ λ°μνκ³ μμ΅λλ€.
μ¦, μ§κΈκ³Ό κ°μ μμ λ°©μμ λ¬Έμ μ μ λ€μκ³Ό κ°μ΅λλ€.
- OCP μλ°°
- μμ€ν μ΄ μ»€μ Έμ νμ₯μ΄ λ κ²½μ° λ©μλμ μ€λ³΅λ¬Έμ λ°μ
λ°λΌμ μ΄λ₯Ό ν΄κ²°νκ³ μ μ λ΅ ν¨ν΄μ μ¬μ©νλ €κ³ ν©λλ€.
2. μ λ΅ ν¨ν΄ ꡬν
μ΄λ²μλ μμ κ°μ΄ μ λ‘λ₯Ό λ°λΌ μ΄λνλ λ²μ€κ° κ°λ°λ μν©μμ μμ€ν μ΄ μ μ°νκ² λ³κ²½λκ³ νμ₯λ μ μλλ‘ μ λ΅ ν¨ν΄μ μ¬μ©ν΄λ³΄λλ‘ νκ² μ΅λλ€.
1)
λ¨Όμ μ λ΅μ μμ±νλ λ°©λ²μ λλ€.
νμ¬ μ΄μ‘μλ¨μ μ λ‘λ₯Ό λ°λΌ μμ§μ΄λ μ§, λλ‘λ₯Ό λ°λΌ μμ§μ΄λ μ§ λ κ°μ§ λ°©μμ΄ μμ΅λλ€.
μ¦, μμ§μ΄λ λ λ°©μμ λν΄ Strategy ν΄λμ€λ₯Ό μμ±νλλ‘ ν©λλ€. ( RailLoadStrategy, LoadStrategy )
κ·Έλ¦¬κ³ λ ν΄λμ€λ move() λ©μλλ₯Ό ꡬννμ¬, μ΄λ€ κ²½λ‘λ‘ μμ§μ΄λμ§μ λν΄ κ΅¬νν©λλ€.
λν λ μ λ΅ ν΄λμ€λ₯Ό μΊ‘μν νκΈ° μν΄ MovableStrategy μΈν°νμ΄μ€λ₯Ό μμ±ν©λλ€.
μ΄λ κ² μΊ‘μνλ₯Ό νλ μ΄μ λ μ΄μ‘μλ¨μ λν μ λ΅ λΏλ§ μλλΌ,
λ€λ₯Έ μ λ΅λ€( μλ₯Ό λ€μ΄, μ£Όμ λ°©μμ λν μ λ΅ λ±)μ΄ μΆκ°μ μΌλ‘ νμ₯λλ κ²½μ°λ₯Ό κ³ λ €ν μ€κ³μ λλ€.
μ΄λ₯Ό μ½λλ‘ νννλ©΄ λ€μκ³Ό κ°μ΅λλ€.
public interface MovableStrategy {
public void move();
}
public class RailLoadStrategy implements MovableStrategy{
public void move(){
System.out.println("μ λ‘λ₯Ό ν΅ν΄ μ΄λ");
}
}
public class LoadStrategy implements MovableStrategy{
public void move() {
System.out.println("λλ‘λ₯Ό ν΅ν΄ μ΄λ");
}
}
2)
λ€μμΌλ‘ μ΄μ‘ μλ¨μ λν ν΄λμ€λ₯Ό μ μν μ°¨λ‘μ λλ€.
κΈ°μ°¨μ λ²μ€ κ°μ μ΄μ‘ μλ¨μ move() λ©μλλ₯Ό ν΅ν΄ μμ§μΌ μ μμ΅λλ€.
κ·Έλ°λ° μ΄λ λ°©μμ μ§μ λ©μλλ‘ κ΅¬ννμ§ μκ³ , μ΄λ»κ² μμ§μΌ κ²μΈμ§μ λν μ λ΅μ μ€μ νμ¬, κ·Έ μ λ΅μ μμ§μ λ°©μμ μ¬μ©νμ¬ μμ§μ΄λλ‘ ν©λλ€.
κ·Έλμ μ λ΅μ μ€μ νλ λ©μλμΈ setMovableStrategy()κ° μ‘΄μ¬ν©λλ€.
μ΄λ₯Ό μ½λλ‘ νννλ©΄ λ€μκ³Ό κ°μ΅λλ€.
public class Moving {
private MovableStrategy movableStrategy;
public void move(){
movableStrategy.move();
}
public void setMovableStrategy(MovableStrategy movableStrategy){
this.movableStrategy= movableStrategy;
}
}
public class Bus extends Moving{
}
public class Train extends Moving{
}
3)
μ΄μ Trainκ³Ό Bus κ°μ²΄λ₯Ό μ¬μ©νλ Clientλ₯Ό ꡬνν μ°¨λ‘μ λλ€.
Trainκ³Ό Bus κ°μ²΄λ₯Ό μμ±ν νμ, κ° μ΄μ‘ μλ¨μ΄ μ΄λ€ λ°©μμΌλ‘ μμ§μ΄λμ§ μ€μ νκΈ° μν΄ setMovableStrategy() λ©μλλ₯Ό νΈμΆν©λλ€.
κ·Έλ¦¬κ³ μ λ΅ ν¨ν΄μ μ¬μ©νλ©΄ νλ‘κ·Έλ¨ μμΌλ‘ λ‘μ§μ΄ λ³κ²½ λμμ λ, μΌλ§λ μ μ°νκ² μμ μ ν μ μλμ§ μ΄ν΄λ³΄κΈ° μν΄
μ λ‘λ₯Ό λ°λΌ μμ§μ΄λ λ²μ€κ° κ°λ°λμλ€λ μν©μ λ§λ€μ΄ λ²μ€μ μ΄λ λ°©μ μ λ΅μ μμ νμ΅λλ€.
public class Client {
public static voidmain(String args[]){
Moving train =newTrain();
Moving bus =newBus();
/*
κΈ°μ‘΄μ κΈ°μ°¨μ λ²μ€μ μ΄λ λ°©μ
1) κΈ°μ°¨ - μ λ‘
2) λ²μ€ - λλ‘
*/
train.setMovableStrategy(newRailLoadStrategy());
bus.setMovableStrategy(newLoadStrategy());
train.move();
bus.move();
/*
μ λ‘λ₯Ό λ°λΌ μμ§μ΄λ λ²μ€κ° κ°λ°
*/
bus.setMovableStrategy(newRailLoadStrategy());
bus.move();
}
}
μ΄μμΌλ‘ μ λ΅ ν¨ν΄μ΄ 무μμΈμ§μ λν΄ μμ보μμ΅λλ€.
Javaμμλ μ¬λ¬ λμμΈ ν¨ν΄μ μ¬μ©νκ³ μλλ° Strategy ν¨ν΄μ μ¬μ©νκ³ μλ APIλ λ€μκ³Ό κ°μΌλ©°, μ°Έκ³ νμλ©΄ μ’μ κ² κ°μ΅λλ€. ( μ°Έκ³ λ§ν¬ )
Strategy
recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of a different abstract/interface type which has been passed-in as method argument into the strategy implementation
[java.util.Comparator#compare()](https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#compare-T-T-)
, executed by among othersCollections#sort()
.[javax.servlet.http.HttpServlet](http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html)
, theservice()
and alldoXXX()
methods takeHttpServletRequest
andHttpServletResponse
and the implementor has to process them (and not to get hold of them as instance variables!).[javax.servlet.Filter#doFilter()](http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-)