프로그래밍하다 보면 특정 목적에 따라 사용해야 하는 개체들이 서로 호환성이 있어야 하는 경우가 발생합니다.
목적에 따라 사용해야 하는 개체군이 다른 경우에 특정 목적에 맞게 호환성있는 개체가 무엇인지를 조사하고 주의 깊게 사용하는 비용이 발생합니다.
접기
#include<iostream> #include<conio.h> #include<string> #include<vector>
using namespace std;
class Lens { public: virtual void Take()=0; };
class EvLens : public Lens { public: virtual void Take() { cout <<"부드럽다"<< endl; } void AutoFocus() { cout <<"Auto Focus"<< endl; } };
class HoLens : public Lens { public: virtual void Take() { cout <<"자연스럽다"<<endl; } void ManualFocus() { cout << "사용자의 명령대로 초첨을 잡다"<<endl; } };
class Camera { Lens *lens; public: virtual bool TakeAPicture() { if(lens==0) { return false; } lens->Take(); return true; } virtual bool PutInLens(Lens *lens)=0; Lens* GetOutLens() { Lens *re=lens; lens=0; return re; } protected: Camera() { lens=0; } void SetLens(Lens *_lens) { lens=_lens; } Lens* GetLens() { return lens; } };
//ev카메라 class EvCamera : public Camera { public: virtual bool TakeAPicture() { Lens *lens=Camera::GetLens(); EvLens *evlens=dynamic_cast<EvLens*>(lens); if(evlens==0) { return false; } evlens->AutoFocus(); return Camera::TakeAPicture(); } virtual bool PutInLens(Lens *lens) { EvLens *evlens=dynamic_cast<EvLens*>(lens); if(evlens==0) { return false; } Camera::SetLens(lens); return true; }
};
//ho카메라 class HoCamera : public Camera { public: virtual bool TakeAPicture() { Lens *lens=Camera::GetLens(); HoLens *holens=dynamic_cast<HoLens*>(lens); if(holens==0) { return false; } holens->ManualFocus(); return Camera::TakeAPicture(); } virtual bool PutInLens(Lens *lens) { HoLens *holens=dynamic_cast<HoLens*>(lens); if(holens==0) return false; Camera::SetLens(holens); return true; } };
typedef vector<Camera*>Cameras; typedef vector<Lens*> Lenses; typedef vector<Camera*>::iterator CIter; typedef vector<Lens*>::iterator LIter;
//추상 팩토리 class DayFactory { Cameras cameras; Lenses lenses; public: virtual Camera *CreateCamera()=0; virtual Lens *CreateLens()=0; ~DayFactory() { DisposeLens(); DisposeCameras(); } protected: void PutCamera(Camera *camera) { cameras.push_back(camera); } void PutLens(Lens *lens) { lenses.push_back(lens); }
private: void DisposeCameras() { CIter iter=cameras.begin(); CIter end=cameras.end(); Camera *camera=0; for(;iter!=end;++iter) { camera=*iter; delete camera; } } void DisposeLens() { LIter iter=lenses.begin(); LIter end=lenses.end(); Lens *lens=0; for(;iter!=end;++iter) { lens=*iter; delete lens; } } };
class EvDayFactory : public DayFactory { public: virtual Camera* CreateCamera() { return new EvCamera; } virtual Lens* CreateLens() { return new EvLens; } };
class HoDayFactory : public DayFactory { public: virtual Camera* CreateCamera() { return new HoCamera; }
virtual Lens* CreateLens() { return new HoLens; } };
//팩토리를 통해 생성된 카메라와 렌즈를 이용하는 클라이언트 클래스임.. class Tester { DayFactory *factories[2]; public: Tester() { Initialize(); } ~Tester() { delete factories[0]; delete factories[1]; } void Test() { TestDirect(); TestUsingFactory(); } private: void Initialize() { factories[0]=new EvDayFactory; factories[1]=new HoDayFactory; }
//호환성 테스트 void TestCase(Camera *camera, Lens *lens) { cout << "테스트"<<endl; if(camera->PutInLens(lens)==0) { cout <<"카메라에 렌즈가 장착이 되지 않았다"<< endl; } if(camera->TakeAPicture()==0) { cout<<"사진이 찍히지 않았습니다"<<endl; } } //직접 카메라와 렌즈를 생성하여 호환성 테스트 //근데 왜 ev카메라와 ho렌즈만 했을까.. void TestDirect() { Camera *camera=new EvCamera; Lens *lens=new HoLens; TestCase(camera,lens); delete camera; delete lens; }
//팩토리를 통해 호환성 테스트 void TestUsingFactory() { //ev 카메라 렌즈 테스트 Camera *camera=factories[0]->CreateCamera(); Lens *lens=factories[0]->CreateLens(); TestCase(camera,lens);
//Ho 카메라 렌즈 테스트 camera=factories[1]->CreateCamera(); lens=factories[1]->CreateLens(); TestCase(camera,lens); }
};
int main() { Tester *tester=new Tester(); tester->Test(); delete tester; getch(); return 0; }
접기