본문 바로가기
CS(Computer Science)지식/[C++] 디자인 패턴

전략 패턴(Strategy Pattern) 이해하기 : 쉽게 설명한 디자인 패턴(C++)

by 엔지니어 청년 2023. 7. 3.

 

안녕하세요. 이번 포스트에서는 전략 패턴(Strategy Pattern)에 대해 알아보도록 하겠습니다. 전략 패턴은 행동 디자인 패턴 중 하나로, 알고리즘을 캡슐화하여 실행 시에 알고리즘을 변경할 수 있게 하는 패턴입니다. 그러면 이번에는 전략 패턴이 무엇인지, 어떻게 사용하는지에 대해 자세히 살펴보겠습니다.

전략 패턴이란?


전략 패턴은 객체의 행동을 캡슐화하고, 이를 객체 안에서 동적으로 바꿀 수 있게 해주는 디자인 패턴입니다. 즉, 객체가 할 수 있는 행동 각각을 전략으로 만들어, 행동하는 방식을 동적으로 바꿀 수 있도록 해주는 패턴입니다. 이로 인해 행동을 클래스로 캡슐화하고, 이를 인터페이스로 사용함으로써 코드의 유연성과 확장성이 향상됩니다.

예시를 통한 이해


전략 패턴의 사용을 이해하기 위해 교통수단을 선택하는 애플리케이션을 만드는 예제를 들어보겠습니다. 이 애플리케이션은 거리, 시간, 비용 등의 조건에 따라 가장 적합한 교통수단을 추천해 줍니다.

우선, 전략을 정의할 인터페이스가 필요합니다. 이를 TravelStrategy라고 합시다.

class TravelStrategy {
public:
    virtual void travel() = 0;
};

다음으로, 이 인터페이스를 구현하는 각 전략(교통수단)을 정의합니다. 예를 들어, BusTravelStrategy, TrainTravelStrategy, CarTravelStrategy 등입니다.

class BusTravelStrategy : public TravelStrategy {
public:
    void travel() override {
        cout << "Traveling by bus!" << endl;
    }
};

class TrainTravelStrategy : public TravelStrategy {
public:
    void travel() override {
        cout << "Traveling by train!" << endl;
    }
};

class CarTravelStrategy : public TravelStrategy {
public:
    void travel() override {
        cout << "Traveling by car!" << endl;
    }
};

마지막으로, 이 전략을 사용할 Traveler 클래스를 정의합니다.

class Traveler {
private:
    TravelStrategy* strategy_;

public:
    Traveler(TravelStrategy* strategy) : strategy_(strategy) {}

    void setStrategy(TravelStrategy* strategy) {
        this->strategy_ = strategy;
    }

    void travel() {
        strategy_->travel();
    }
};

이제 이 애플리케이션을 사용하면 다음과 같습니다.

int main() {
    Traveler* traveler = new Traveler(new BusTravelStrategy());
    traveler->travel();  // Traveling by bus!

    traveler->setStrategy(new TrainTravelStrategy());
    traveler->travel();  // Traveling by train!

    delete traveler;

    return 0;
}

여기서는 Traveler 객체가 어떤 TravelStrategy 객체를 사용할지 결정하는 것을 볼 수 있습니다. 그리고 그 결정은 실행 시간에 이루어집니다. 이것이 바로 전략 패턴의 핵심입니다.

마치며


이처럼 전략 패턴은 특정한 계산이나 행동의 전략을 캡슐화하여, 실행 시간에 알고리즘을 선택할 수 있게 하는 디자인 패턴입니다. 이로 인해 알고리즘을 사용하는 클라이언트와 독립적으로 알고리즘을 변경하거나 확장할 수 있습니다.

전략 패턴은 알고리즘의 유연성을 확보하고, 알고리즘을 사용하는 클라이언트와의 결합도를 낮춰 코드의 유지보수를 용이하게 합니다. 따라서 상황에 따라 동적으로 알고리즘을 변경해야 하는 경우 전략 패턴을 고려해 보세요.

이상으로 전략 패턴에 대한 설명을 마치겠습니다. 다음 시간에는 다른 디자인 패턴에 대해 알아보도록 하겠습니다. 감사합니다.

 

추가 예시 통신 방식 결정

// 통신 방식을 추상화한 인터페이스
class CommInterface {
public:
    virtual ~CommInterface() {}
    virtual void receiveData() = 0;  // 데이터를 받아오는 메서드
};

// I2C 통신을 구현한 클래스
class I2CComm : public CommInterface {
public:
    void receiveData() override {
        // I2C 통신으로 데이터를 받아오는 코드
    }
};

// SPI 통신을 구현한 클래스
class SPIComm : public CommInterface {
public:
    void receiveData() override {
        // SPI 통신으로 데이터를 받아오는 코드
    }
};

// 통신 방식을 사용하는 클라이언트 클래스
class CommClient {
private:
    CommInterface* strategy;  // 통신 방식을 나타내는 전략

public:
    CommClient(CommInterface* strategy) : strategy(strategy) {}

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

    void receiveData() {
        strategy->receiveData();  // 선택된 전략을 사용하여 데이터를 받아옴
    }
};