[C++][Design Pattern] 디자인 패턴 기본과 의존성 주입

디자인 패턴이란?

프로그램을 구성하는 표준화된 접근 방법론 (프로그램을 어떻게 구성해야 좋은 프로그램이냐?에 대한 답), C++은 객체지향 언어이므로 객체들의 구성과 관계를 표현하는 데 특화된 객체지향 패턴을 많이 사용한다.


의존성 주입

의존성 주입을 적용하면 서비스에 대한 목업을 쉽게 만들 수 있어 단위 테스트(Unit Test)를 쉽게 할 수 있다.

컴포넌트 ---필요하다---> 서비스

위와 같은 관계에서 서비스에 대한 인터페이스를 컴포넌트에 주입한다.


예를 들어 임베디드 시스템에서 어떤 컴포넌트가 하드웨어 모듈의 레지스터에 대해 Read/Write하는 서비스가 필요한 경우에 IAccessRegister라는 인터페이스를 사용하도록 강제할 수 있다. 이렇게 하면 단위 테스트 시에 IAccessRegister 인터페이스에 대해 목업 구현을 하여 해당 서비스 이용에 대해 검사할 수 있다.


IAccessRegister 예제는 아래와 같다.

class IAccessRegister

{

    public:

        virtual ~IAccessRegister() = default;


        virtual void SetRegisterA(UINT32 value) = 0;

        virtual UINT32 GetRegisterA(void) = 0;

};


AccessRegister 클래스의 구현은 다음과 같다.

class AccessRegister : public IAccessRegister

{

    public:

        void SetRegisterA(UINT32 value) override;

        UINT32 GetRegisterA(void) override;

    private:

        UINT32 registerDesignator;

};


void AccessRegister::SetRegisterA(UINT32 value)

{

    registerDesignator = 'A';

    // doSomething with value

}


UINT32 AccessRegister::GetRegisterA(void)

{

    registerDesignator = 'A';

    // doSomething and return

}

이제 레지스터 접근을 CoreManager 컴포넌트에서 한다고 해보자.

class CoreManager

{

    public:

        CoreManager(IAccessRegister& accessRegister) : m_accessRegister { accessRegister } { }

        void WriteRegisterA(UINT32 value)

        {

            m_accessRegister.setRegisterA(value);

        }

    private:

        IAccessRegister& m_accessRegister;

};

위처럼 구성하면 CoreManager 컴포넌트 생성 시에 Access Register를 주입할 수 있다.

AccessRegister accessRegister;

CoreManager coreManager { accessRegister };

coreManager.WriteRegisterA(someValue);


댓글