[Java] 전략패턴이란?

김영훈·2024년 4월 1일

Area

목록 보기
4/5
post-thumbnail

전략패턴이란?

📌 객체의 행동을 실행 시간에 변경할 수 있도록 해주는 디자인 패턴 중 하나
알고리즘의 일부분을 변경하고 싶을 때 전략 패턴을 사용

간단하게 말해서 객체가 할 수 있는 행위들 각각을 전략으로 만들어 놓고, 동적으로 행위의 수정이 필요한 경우 전략을 바꾸는 것만으로 행위의 수정이 가능하도록 만든 패턴이다.

간단한 예시와 함께 전략 패턴을 사용해보자.

public interface FlyBehavior  {
	public void fly();
}
public interface QuackBehvior {
	public void quack();
}
public abstract class Duck {
	FlyBehavior flyBehavior;   // interface
	QuackBehvior quackBehvior; // interface

	public void swim(){
		System.out.println("오리가 헤엄친다!")
	}

	public abstract void display(); // abstract 메서드는 상속받으면 반드시 오버라이딩
	
	public void performQuack(){
		quackBehvior.quack();
	}
	
	public void performFly(){
		flyBehavior.fly();
	}

}

FlyBehaviorQuackBehvior interface를 가지고 있는 abstract class Duck을 만들어준다. 매우매우 간단한 구조를 가지고 있다.

FlyBehavior(비행방법)엔 무엇이 있을까? 간단하게 몇 가지만 구현해보자.

public class FlyNoWay implements FlyBehavior{
	@Override  
	public void fly() {  
	    System.out.println("날지 못하는 슬픈 짐승이여...");  
	}
}

저런.. 나는 법을 모르는 FlyBehavior 였다... 날 수 있는 오리를 만들기 위해 하늘을 날 수 있는
FlyBehavior를 만들어보자!

public class FlyWithWings implements FlyBehavior{
	@Override  
	public void fly() {  
	    System.out.println("멋진 달이 될래요!");  
	}
}

날개로 날 수 있는 FlyBehavior를 만들었다! 더 이상 오리는 날 수 없다 엄마에게 혼나지 않는 오리를 만들 수 있을 듯 하다.

QuackBehvior(우는방법)엔 무엇이 있을까? 간단하게 몇 가지만 구현해보자!

public class Quack implements QuackBehavior{
	@Override  
	public void quack() {  
	    System.out.println("오리가 꽥꽥 울어요!");  
	}
}	

평범하게 우는 오리를 만들 수 있을 듯 하다.

public class Squeak implements QuackBehavior{  
    @Override  
    public void quack() {  
        System.out.println("장난감 오리에서 꽉꽉 소리가 나요!");  
    }  
}

이번엔 장난감 오리의 울음소리를 만들어 봤다.

public class MuteQuack implements QuackBehavior{  
    @Override  
    public void quack() {  
        System.out.println("소리가 나지 않는다.");  
    }  
}

울지 못하는 오리를 위한MuteQuack

이제 마지막으로, 다양한 오리를 만들어보자!

public class MallardDuck extends Duck{  
    public MallardDuck() {  
        quackBehavior = new Quack();  // 평범하게 우는 Behavior
        flyBehavior = new FlyWithWings();  // 날개로 하늘을 나는 Behavior
    }  
  
    @Override  
    public void display() {  
        //천둥오리  
        System.out.println("천둥오리처럼 보인다.");  
    }  
}
public class RubberDuck extends Duck{  
    public RubberDuck() {  
        flyBehavior = new FlyNoWay();  // 날 수 없는 Behavior
        quackBehavior = new Squeak();  // 장난감 오리의 울음소리 Behavior
    }  
  
    @Override  
    public void display() {  
        System.out.println("고무오리처럼 보인다.");  
    }  
}
public class DecoyDuck extends Duck{  
    public DecoyDuck() {  
        quackBehavior = new MuteQuack();  // 울지 못하는 Behavior
        flyBehavior = new FlyNoWay();  // 날 수 없는 Behavior
    }  
  
    @Override  
    public void display() {  
        System.out.println("가짜 오리 처럼 보인다.");  
    }  
}

장난감 오리(고무오리), 천둥오리, 가짜 오리를 만들어 보았다!
그런데 대체 어떤 이점이 있길래 이렇게 만드는 걸까?
잠시 간단한 예제를 통해 알아보자.

public class DuckDriver{
	public static void main(String[] args) {
		List<Duck> duckList = new ArrayList<>();
		// Duck 리스트 생성!
		duckList.add(new MallardDuck());
		duckList.add(new DecoyDuck());
		duckList.add(new RubberDuck());
		// 천둥오리, 가짜오리, 고무오리 모두 들어가!
		duckList.forEach(Duck::display); // -> 메서드 참조
		// duckList에 들어있는 오리들, 다들 자기 생김새를 말해봐!
	}
}

실행결과

천둥오리처럼 보인다.
고무오리처럼 보인다.
가짜 오리 처럼 보인다.

매우 신기하게도, 천둥오리.display()장난감오리.display() 와 같이 특정 대상 명령을 하지 않고 (Duck::display) 로 사용했는데도 불구하고 알아서 차례대로 결과값이 나온다!

public class DuckDriver{
	public static void main(String[] args) {
		List<Duck> duckList = new ArrayList<>();
		// Duck 리스트 생성!
		duckList.add(new MallardDuck());
		duckList.add(new DecoyDuck());
		duckList.add(new RubberDuck());
		// 천둥오리, 가짜오리, 고무오리 모두 들어가!
		duckList.forEach(Duck::display); // -> 메서드 참조
		// duckList에 들어있는 오리들, 다들 자기 생김새를 말해봐!
		duckList.forEach(Duck::performQuack);  
		duckList.forEach(Duck::performFly);
		// 물론 우는 방법이나 나는 방법에도 적용된다!
	}
}

이처럼 전략 패턴은 객체의 행동을 실행 시간에 변경할 수 있도록 해준다!


0개의 댓글