Review - abstract class
- 순수 가상함수(pure virtual function)를 하나 이상을 가지는 클래스로서 객체를 생성할 수 없음
- 파생 클래스에서 특정 함수를 반드시 구현하도록 지시함
#include <iostream> using namespace std; // 추상 클래스 class Shape { public: virtual void Draw () = 0; // 순수 가상함수 }; // 순수 가상함수를 모두 구현한 파생 클래스, 객체 생성 가능 class Circle : public Shape { public: void Draw () override { cout << "Draw a Circle" << endl; } }; // Draw를 구현하지 않으면 역시 추상 클래스임, 객체 생성 불가 class Rect : public Shape {};
Open-Closed Principle (OCP)
- 기능 확장에는 열려 있고(open), 코드 수정에는 닫혀 있어야(closed) 한다는 이론
- 미래에 새로운 클래스가 추가되어도 과거의 코드는 수정되면 안된다.
아래의 예제 코드를 살펴보자.
#include <iostream>
using namespace std;
class Camera
{
public:
void Take () { cout << "take picture with Camera" << endl; }
};
class People
{
public:
void UseCamera (Camera* p) { p->Take(); }
};
int main (int argc, char* argv[])
{
Camera c1;
People p;
p.UseCamera(&c1);
return 0;
}
여기에 새로운 종류의 카메라(Camera2)가 추가되었다고 해보자.
class Camera2
{
public:
void Take () { cout << "take picture with Camera2" << endl; }
};
Camera2를 People 객체가 사용하려면 People 객체도 아래와 같이 수정되어야 한다.
class People
{
public:
void UseCamera (Camera* p) { p->Take(); }
void UseCamera (Camera2* p) { p->Take(); } // function overloading
};
Camera2 클래스가 추가됨에 따라 기존 클래스인 People에 새로운 함수 하나가 추가되었다. 현재 구조로는 새로운 카메라 타입이 추가될 때마다 동일한 작업이 필요하게 될 것이다.
이제는 위의 코드를 OCP를 만족하도록 수정해보자. 우선 카메라 제작자와 카메라 사용자 사이에 지켜야하는 규칙을 추상 클래스를 이용해서 만들자.
// 카메라 제작자가 지켜야 할 규칙(약속, 인터페이스)
// 모든 카메라는 아래의 인터페이스를 구현해야 한다.
class ICamera
{
public:
virtual ~ICamera () {}
virtual void Take () = 0;
};
// 실제 카메라는 없지만 규칙이 존재한다. 사용자는 규칙대로만 사용하면 된다.
// 새로운 카메라가 추가되더라도 People 클래스는 수정하지 않아도 된다.
class People
{
public:
void UseCamera (ICamera* p) { p->Take(); }
};
이제는 새로운 카메라 클래스를 추가할 때에는 ICamera에서 정의한 인터페이스를 따르기만 하면 기존 코드인 People 클래스는 수정하지 않아도 된다.
#include <iostream>
using namespace std;
// 모든 카메라 제작자는 규칙을 지켜야 한다.
// People과 Camera, Camera2는 약한 결합(loosely coupling) 상태
class Camera : public ICamera
{
public:
void Take () override { cout << "take picture with Camera" << endl; }
};
class Camera2 : public ICamera
{
public:
void Take () override { cout << "take picture with Camera2" << endl; }
};
int main (int argc, char* argv[])
{
People p;
// 이제 UseCamera는 함수 오버로딩이 아닌 하나의 함수이다.
// 즉, 카메라의 종류에 상관없이 하나의 인터페이스를 사용한다.
Camera c1; p.UseCamera(&c1);
Camera2 c2; p.UseCamera(&c2);
return 0;
}
'NC University > Design Pattern with C++' 카테고리의 다른 글
1일차 - 상속(inheritance) (0) | 2016.05.24 |
---|---|
1일차 - thiscall (0) | 2016.05.19 |