본문 바로가기
CS 전공지식 정리/디자인 패턴

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

by code_killer 2023. 10. 22.
728x90
반응형

1. 전략 패턴(Strategy Pattern)이란?

  • 객체의 행위를 바꾸고 싶을 때, '직접' 수정이 아닌 전략이라고 부르는 '캡슐화한 알고리즘'을 컨텍스트 안에서 바꿔주면서 상호 교체가 가능한 패턴
#include <iostream>

using namespace std;

// Strategy Interface
class Strategy {
public:
	virtual int doOperation(int num1, int num2) = 0;
};

// Concrete Strategies
class Add : public Strategy {
public:
	int doOperation(int num1, int num2) override {
		return num1 + num2;
	}
};

class Subtract : public Strategy {
public:
	int doOperation(int num1, int num2) override {
		return num1 - num2;
	}
};

class Multiply : public Strategy {
public:
	int doOperation(int num1, int num2) override {
		return num1 * num2;
	}
};

// Context
class Calcualtor {
private:
	Strategy* strategy;

public:
	Calcualtor(Strategy* initialStrategy) : strategy(initialStrategy) {}

	void setStrategy(Strategy* newStrategy) {
		this->strategy = newStrategy;
	}

	int executeStrategy(int a, int b) {
		return this->strategy->doOperation(a, b);
	}
};

int main() {
	Calcualtor calculator(new Add());

	cout << "10 + 5 = " << calculator.executeStrategy(10, 5) << endl;

	calculator.setStrategy(new Subtract());
	cout << "10 - 5 = " << calculator.executeStrategy(10, 5) << endl;

	calculator.setStrategy(new Multiply());
	cout << "10 * 5 = " << calculator.executeStrategy(10, 5) << endl;

	return 0;
}

 

2. 전략 패턴의 장점

 1. 유연성

  - 실행 시간에 알고리즘을 선택하거나 변경할 수 있음

2. 결합도 감소

 - 클라이언트와 알고리즘 코드 사이의 결합도를 줄여줌. 클라이언트 코드는 전략 객체에 대한 참조만 가지며, 실제 구현 세부사항에 대해서는 알 필요가 없음

3. 확장성

 - 새로운 전략(알고리즘)을 추가하는 것이 비교적 간단. 기존 코드를 수정하지 않고도 새로운 전략 클래스를 추가하기만 하면 됨

4. 테스트 용이성

 - 각각의 전략들을 독립적으로 테스트 가능하며, 클라이언트 코드와 분리하여 테스트 가능

 

3. 전략 패턴의 단점

 1. 클래스 수 증가

  - 각각의 알고리즘이 별도의 클래스로 구현되므로, 많은 수의 클래스가 생성될 수 있음

 2. 클라이언트와 전략 사이의 의사소통

  - 클라이언트가 올바른 전략 객체를 선택하고 사용해야 함. 이 과정에서 오류가 발생할 가능성도 있으며, 복잡한 상황에서는 이해하기 어려울 수도 있음

 3. 상태 관리 문제

  - 일부 경우에는 상태 정보를 저장하거나 관리해야 할 필요가 있는데, 여러 개의 서로 다른 전략 객체들 사이에서 상태 정보를 공유하는 것이 복잡해짐

 

4. 전략패턴의 대표적인 예

 1) passport 라이브러리

  • Node.js에서 인증 모듈을구현할 때 쓰는 미들웨어 라이브러리로, 여러 가지 '전략'을 기반으로 인증할 수 있음
  • 서비스 내의 회원가입된 아이디와 비밀번호를 기반으로 인증하는 LocalStrategy 전략과 페이스북, 네이버 등 다른 서비스를 기반으로 인증하는 OAuth 전략 등을 지원
var passport = require('passport'), LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy(
	function(username, password, done) {
    	User.findOne({ username: username }, function (err, user) {
        	if (err) { return done(err); }
            if (!user) {
            	return done(null, false, { message: 'Incorrect username.'});
            }
            if (!user.validPassword(password)) {
            	return done(null, false, { message: 'Incorrect password.'});
            }
            return done(null, user);
        });
    }
));
728x90