본문 바로가기
소프트웨어공학/디자인 패턴

Strategy Pattern ㅡ 행위, 행동(Behavior)을 인터페이스로 추상화 시켜 구성(composition)을 통해 행동들을 사용 | Design Pattern 디자인 패턴

by javapp 자바앱 2021. 11. 4.
728x90

 

 

Strategy Pattern

 

클래스별로 캡슐화되어 있는 객체들을 교체할 수 있도록 함으로써 같은 작업을 다른 알고리즘으로 사용할 수 있도록 하는 패턴

 

  • Strategy 클래스 내 각각 캡슐화 그리고 구성을 통해 알고리즘 바꿀 수 있다.
  • Strategy Pattern 은 클라이언트가 독립적으로 다양한 알고리즘을 사용한다.
    • 다형성을 이용하여 특정 객체에 종속되지 않도록 한다. 다른 부분을 분리하여 캡슐화한다.

 

상속하지 않는 대신 인터페이스를 통해 캡슐화(추상화)한다. (상속 대신 구성 사용)

분리된 strategies 인터페이스에서 behaviors(행동)이 정의된다.

behavior 과 behavior을 사용하는 class 사이에는 더 나은 decoupling 이다.

Behaviors 는 런타임시에도 변경할 수 있다.

 

 

* 캡슐화 : 구조적 설계에서 모듈화와 같은 의미로 객체를 정의할 때 연관된 속성과 방법을 한 테두리로 묶는 것

* 다형성 : 상속받은 여러 개의 하위 객체들이 다른 형태의 특성을 갖는 객체로 이용될 수 있는 성질

 

 


 

 

 

Strategy Pattern 은 코드상 어떤 문제점이 있을 때 활용할 수 있을까?

 

상속을 통해 행동을 확장하고

슈퍼 클래스에 새로운 행동을 추가했다.

 

슈퍼 클래스에 추가된 fly()는

모든 subclass 에게 적용되고 영향을 준다.

 

 

 

 

 

 

 

 

문제점)

  • 각 subclass 에서 원하지 않는 결과가 발생하는 지 검사

ex) 고무오리는 날지 못함

 

  • 슈퍼클래스에 추가된 fly() 는 모든 subclass 에게 적용된다.

 

 

 

 

문제 해결)

 

Duck 클래스 에서 fly()를 분리하고 캡슐화 한다.

 

클래스(애플리케이션)에서

변경 가능한 부분을 분리하고 추상화 / 캡슐화 한다.

-->> OCP : 닫힘은 추상화에 기반, 변경 가능성 있는 부분을 추상화한다.

 

 

 

※ (abstract) class vs interface

(설계원칙) interface에 맞춰 프로그래밍 

구현에서 실제 변수 ,메소드 변경에 영향을 받을 수 있다.

공유되는 코드가 많을 때 추상클래스

 

 

 

 

 

(설계원칙) 상속 inheritance 보다 구성 composition.

 

분리한 코드에 구성을 사용하여 통합한다.

 

 

 

 

 

 

 

 

Polymorphic Composition 을 통한 클래스의 행동 확장

  1. 클래스에서 변경 가능한 부분을 분리하고 추상화
  2. 분리한 부분을 구성을 사용하여 통합

 

 

 

 

 

Polymorphic Composition) interface 구성

Composition of Abstraction(interface) (not Concretion) / 구현X -> 변경영향 적음

Strategy or Policy : 행동을 추상화한 클래스

interface > 추상(abstract) > 구상(concrete)

 

 

 

추상화

// Strategy: fly() 행동 추상화
public interface FlyBehavior {
	public void fly();
}

 

행동 구현

// Mechanisms: Strategy를 구현함
public class FlyWithWings implements FlyBehavior { 

	public void fly() { 
		System.out.println("I'm flying!!"); 
	}
}

public class FlyNoWay implements FlyBehavior {
	public void fly() { 
		System.out.println("I can't fly"); 
	}
}

 

Polymorphic Composition

// swim, fly, setFlyBehavior은 동일 
public abstract class Duck  // Context
{ 
	FlyBehavior flyBehavior; // Polymorphic Composition

	abstract void display();
	public void swim() { System.out.println("All ducks float, even decoys!"); }
	public void fly() { flyBehavior.fly(); } // Delegation

	// 실행 중 행동 변경도 가능
	public void setFlyBehavior(FlyBehavior fb) {  flyBehavior = fb; }
}

 

subclass 들이

공유하는 코드는 abstract에서 구현

 

public void swim() { System.out.println("All ducks float, even decoys!"); }
public void fly() { flyBehavior.fly(); } // Delegation

// 실행 중 행동 변경도 가능
public void setFlyBehavior(FlyBehavior fb) {  flyBehavior = fb; }

 

 

 

public class MallardDuck extends Duck 
{
	// 생성자에서 자신의 (default) 행동 생성(설정)
	public MallardDuck() { flyBehavior = new FlyWithWings(); }

	public void display() { System.out.println("I'm a real Mallard duck"); }
}

 

 

메인 실행

// client
public class MiniDuckSimulator1  
{
	public static void main(String[] args) {

		Duck mallard = new MallardDuck();
		mallard.fly();

		Duck rubber = new RubberDuck();
		rubber.fly();

		// client가 실행 중 context의 행위 변경 (행동 변경의 유연성↑)
        // 런타임때 행동을 바꿀수 있다.
		rubber.setFlyBehavior(new FlyRocketPowered()); 
		rubber.fly();

	}
}

 

 


 

 

다이어그램

 

인터페이스 (What to do)

추상클래스 : 공유 연산이 많을 때

concreate 클래스(How to do)

 

 

댓글