본문 바로가기
개발자 일지/Java

[디자인패턴]전략 패턴(Strategy Pattern)

by 네빌링 2021. 2. 20.
반응형

-디자인 패턴 중 전략패턴에 대해 알아본다.


전략패턴이란

전략패턴이란 특정 객체의 행위 알고리즘군을 각각 캡슐화하고 필요시에 객체지향 원칙을 위배하지 않고 교환해서 유연하게 사용할 수 있는 패턴이다. 여기서 행위 알고리즘 자체를 '전략'으로 표현하고, 이런 전략을 상황에 맞게 교체해주는 역할을 하는 클래스를 '컨텍스트'라고 표현한다. 컨텍스트는 클라이언트와 전략 사이에서 '접점'역할을 한다.

 

행위 알고리즘 자체는 인터페이스로 설계하고 각자 캡슐화된 행위로 구현한다. 

 

 

Context는 Strategy라는 인터페이스를 접점으로 이용하여 Strategy를 구현한 '전략'을 유연하게 교체하며 사용한다.

 

 

예시

  • 컴퓨터 백신 인스톨러 A, B가 있다고 가정하며 둘다 네이버백신을 설치하는 프로그램. 추후 요구사항이 B 인스톨러의 프로그램을 V3백신으로 바꿔달라는 요구사항이 들어온 경우 전략패턴으로 샤샤샥 바꾸는 예제

 

전략패턴 적용 전 예시

package StrategyBefore;

public interface Installer {
	public void install(); 
}
package StrategyBefore;

public class InstallerA implements Installer {
	@Override
	public void install() {
		System.out.println("네이버백신 설치");
	}

}
package StrategyBefore;

public class InstallerB implements Installer {
	@Override
	public void install() {
		System.out.println("네이버백신 설치");
	}

}
package StrategyBefore;

public class Main {
	public static void main(String[] args) {
		Installer installerA = new InstallerA();
		Installer installerB = new InstallerB();
		
		installerA.install();
		installerB.install();
		
		//요구사항 : installerB의 프로그램을 V3백신으로 바꿔주세요
		//나 : 아...수정할 곳 많은데
	}
}

//결과
//네이버백신 설치
//네이버백신 설치

 

전략패턴 적용 전의 예시이다. 클라이언트(Main)에서 InstallerA,InstallerB의 인스톨을 하면 둘다 '네이버백신 설치'의 결과가 나온다. 근데 이 상황에서 InstallerB의 프로그램을 V3백신으로 바꿔달라는 요청이 온다면 InstallerB를 직접 수정해야 한다. 이는 객체지향원칙 중 OCP원칙에 위배된다.

 

전략패턴 적용 후 예시

 

package Strategy;

public interface Vaccine{
	public void install();
}

 

위의 코드는 install이라는 행위(전략)를 클래스로 캡슐화하기 위한 인터페이스이다.

 

package Strategy;

public class NaverVaccine implements Vaccine{
	@Override
	public void install() {
		System.out.println("네이버백신 설치");
	}
	
}
package Strategy;

public class V3Vaccine implements Vaccine{
	@Override
	public void install() {
		System.out.println("V3백신 설치");
	}
}

 

위의 NaverVaccine, V3Vaccine은 Vaccine 인터페이스를 구현한 캡슐화된 전략이라고 보면 된다. 각각의 설치 행위를 공통 인터페이스(Vaccine)를 통해 추후 접근할 수 있도록 만들었다.

 

package Strategy;

public class Installer {
	private Vaccine vaccine;

	public void setVaccine(Vaccine vaccine) {
		this.vaccine = vaccine;
	}
	
	public void install() {
		vaccine.install();
	}
}

 

위의 Installer 클래스가 클라이언트와 전략 간의 접점역할을 해주는 컨텍스트(Context)이다.

클라이언트 단에서 setVaccine() 함수를 이용하여 유연하게 vaccine을 구현한 전략을 vaccine 변수에 주입한다.

그리고 install() 함수를 통해 vaccine의 install()을 위임받아 실행한다.

 

package Strategy;

public class Main {
	public static void main(String[] args) {
		Installer installerA = new Installer();
		Installer installerB = new Installer();
		
		installerA.setVaccine(new NaverVaccine());	//컨텍스트를 통해 사용할 전략(네이버백신) 셋팅
		installerB.setVaccine(new NaverVaccine());	//컨텍스트를 통해 사용할 전략(네이버백신) 셋팅
		
		installerA.install();	//실행
		installerB.install();	//실행
		
		//요구사항:installerB의 프로그램을 V3백신으로 바꿔주세요
		//나 : 네 다됐습니다 ^_^
		installerB.setVaccine(new V3Vaccine());	//전략을 네이버백신에서 V3백신으로 교체
		installerB.install();	//실행
	}
}

//결과
//네이버백신 설치
//네이버백신 설치
//V3백신 설치

 

위의 클라이언트(Main)에서 setVaccine을 통해 사용할 백신을 선택해준다. 여기서는 installerA,installerB가 모두 네이버백신을 사용한다. 이후 요구사항으로 installerB의 백신프로그램을 V3백신으로 바꿔달라는 요청이 오면 setVaccine을 통해 전략만 교체해주면 된다.

 

토비의스프링3.1의 초반에 UserDao를 통해 Connection객체를 변경해주는 예시에도 전략패턴을 소개하고 있으니 다시 학습해본 후 포스팅 해봐야겠다.

 

 

반응형