템플릿 메서드


 객체의 연산에는 알고리즘의 뼈대만을 정의하고 각 단계에서 수행할 구체적 처리는 서브클래스 쪽으로 미룹니다. 알고리즘의 구조 자체는 그대로 놔둔 채 알고리즘 각 단계처리를 서브클래스에서 재정의할 수 있게 합니다.


-GOF의 디자인패턴 중-











예를 들어 기존 커피와 차를 만드는 코드가 있는데 코코아를 만드는 코드를 만들게 되었습니다.이럴 경우 만드는 순서, 물을 끓이고 컵에 담는 동일 공정이 해야 할 것입니다.



하지만 템플릿 메서드를 사용 할 경우 동일 공정을 부모 클래스에 정의함으로써 코드의 중복과 하드 코딩을 방지 할 수 있습니다. 클래스는 부모클래스인 비버리지와 서브클래스인 커피와 티로 구성되며, 템플릿 메서드로는 음료제작에 대한 알고리즘의 골격을 정의하는 프리퍼레시피가 있습니다. 우선 부모클래스인 비버리지가 서브클래스인 커피와 티에 공통적인 행위에 대하여 정의하면, 자식클래스인 커피와 티는 서로 공통되지 않는 부분에 대하여 정의하고 있습니다. 또한 프로퍼레시피의 코디먼트는 첨가물여부에 대한 훅메소드로 구성되어 있습니다.


여기서 훅메소드는 부모 클래스에 선언되는 메소드이기는 하지만 기본적인 내용만 구현되어 있거나 아무 코드도 들어있지 않은 메소드 입니다. 이를 서브 클래스에서 선택적으로 오버라이드 하여 사용하며, 오버라이드 하지 않으면 부모클래스에서 기본으로 제공한 코드가 실행됩니다.


이러한 템플릿 메서드는 코드의 재사용성을 높일수 있다는점과 일부행동만 지정하는 프레임웍을 만다는데 유용하지만, 서브클래스가 꼭 구현해야할 매서드의 개수가 많아질수록 설계가 복잡해지고, 상속에 의존적이기 때문에 유연성이 떨어지는 단점이 있습니다.


관련패턴으로는 전략패턴이 있는데, 템플릿메서드는 동일알고리즘의 일부분이 다양한 형태를 띄도록 하기 위해 서브클래스에서 처리하고, 

전략패턴은 바꿔쓸수 있는 행동을 캡슐화하고, 어떤행동을 사용할지는 서브클래스에게 위임한다는 차이점이 있습니다. 


#include <iostream> 

 



using std::cout; 

using std::cin; 

using std::endl; 



class Beverage 

public: 

// 템플릿(틀) 메소드. 

// 알고리즘의 각 단계가 파생 클래스에서 수정되는 것을 방지하기 위해 비가상으로 선언.

// 비가상인터페이스 :  private 가상 함수를 감싸는 publice 비가상 함수(비가상 인터페이스)를 만들어 

// 인터페이스를 단일화하는 것을 의미

// 템플릿 메소드 패턴으로 구현

void PrepareRecipe() 

BoilWater(); 

Brew(); 

PourInCup(); 

if ( Condiments() ) // 후킹! 

AddCondiments(); 

}

}

private: 

// 모든 가상 메소드를 정의 해야만 한다.

//가상메소드 정의 (Brew & AddCondiments)

virtual void Brew()=0;

virtual void AddCondiments()=0;

// 후크연산 기본적으로 부모연산은 아무행동도 정의하지 않는다.

// 기본 클래스에 있는 템플릿 메소드의 알고리즘 단계에 파생 클래스가 여러가지 방식으로 개입할 수 있게 된다. 

virtual const bool  Condiments() 

{

return true; 

} //기본값 : 첨가물추가


void BoilWater() { cout << "물 끓이는 중" << endl; } 

void PourInCup() { cout << "컵에 따르는 중" << endl; } 

}; 



class Coffee: public Beverage 

private: 

// 가상메소드 재정의 (Brew & AddCondiments)

void Brew()

{

cout << "커피 우려내는중~"<<endl;

}


//행동확장을 위해 후크연산을 재정의한다.

virtual const bool Condiments() // 후크

cout << "설탕과 우유를 넣으시겠습니까? : 1. 네, 2. 아니오" << endl; 

int answer=0; 

bool res=0;


cin >>answer; 

if (answer ==1)

res = true; 

else if (answer ==2)

res = false;

return res; 

}

void AddCondiments()

{

cout << "우유와 설탕을 추가하는중~"<<endl; 

}

};



class Tea: public Beverage 

private: 

// 가상메소드 재정의 (Brew & AddCondiments)

void Brew()

{

cout << "티백 우려내는중~"<<endl;

}

void AddCondiments()

{

cout << "레몬을 추가하는중~"<<endl; 

}

};



void main()

{

Beverage *cafe = new Coffee();

cafe->PrepareRecipe();


delete cafe;


cout<<"\n\n"<<endl;


cafe = new Tea();

cafe->PrepareRecipe();


delete cafe;


cout<<"\n\n"<<endl;

cafe = new Coffee();

cafe->PrepareRecipe();


delete cafe;

}


'Programing > Design Pattern' 카테고리의 다른 글

상태패턴 예제  (0) 2016.11.30
State Pattern (상태패턴)  (0) 2016.11.30
전략패턴,Strategy patterns  (0) 2016.11.30

전략패턴



전략패턴의 핵심은 객체의 내부에서 나타날 수 있는 행동을 따로 분리하여 여러개로 확장하여 일일이 서브클래스마다 행동에 대한 하드코딩을 피한다는 것입니다.

하드코딩을 하지않는 대신생성자를 통해 매뉴얼(전략)을 선택하여 집어넣으면

끝입니다.


위 상황은 단순한 상황입니다이전 설계 할 때 모든 유닛 오브젝트는Att을 할꺼로 예상하고 베이스 오브젝트에 그 가상함수를 넣어놨습니다.

그리고 3개의 하위 클래스를 설계합니다. Marin,Medic,Tank 근데 문제가하나 있습니다. Medic은 예상을 벗어나 Att에 대한 행동을 정의할 수 없게 되었습니다해병은 총을 쏘고탱크는 캐논샷을 쏘지만 메딕은 공격을 하지 못합니다그래서 설계한 방법으로 베이스 클래스의 Att함수를 오버라이딩해서 {} 이렇게 빈칸으로 두기로 했습니다하지만 이런식으로 베이스 클래스의 가상함수가 늘어날수록 동작을 하지 않아야 되는 함수들을 일일이 오버라이딩으로 처리하여 코딩하는 것은 상당히 귀찮은 일입니다문법때문에 어쩔수 없다는 생각을 가져도 만약 1000개의 오브젝트에서 그런 하드코딩을 하라면….. 더불어 코딩이 실제로 들어가므로 유지보수때도 신경쓸 수 밖에 없습니다예를들어 베이스클래스의 기능이 10가지 인데 메딕은 그중에 3가지 밖에 쓰지 않는다고 가정해 봅시다그럼 나머지 7개를 빈칸으로 오버라이딩 할 수 밖에 없는 것이죠

이때 전략패턴을 사용하면 이런 수고를 덜 수 있을 뿐더러 다른 행동까지도 동적으로 정의할 수 있는 유연성이 생깁니다


위 그림에서 같이 전략패턴에서 전략을 나타내는 객체를 매뉴얼이라고 표현했습니다제가 생각하기에는 매뉴얼이 전략패턴의 컨셉과 잘 맞는것 같습니다전략 패턴의 핵심은 객체의 내부에서나타날 수 있는 행동을 따로 분리하여 여러 개로 확장하여 일일이 서브클래스마다 행동에 대한 하드코딩을 피한다는 것입니다하드코딩을 하지 않는 대신생성자를 통해 매뉴얼(전략)을 선택하여 집어넣으면 끝입니다위에서 Att함수는 그 내부에서 매뉴얼을 참조해서 행동하므로 다른 Att행동을 취할 수 있습니다만약 생성자에 매뉴얼을 넣지 않을때 Att함수는 아무일도 하지않게 설계하면 메딕을 생성하는데 문제가 없습니다





하나는 매개변수를 직접 마련하여 전달하는 형식이고 다른 하나는 객체 자신을 매개변수로 넘겨 접근권한을 주고 처리하게 하는 형식입니다전자는 매개변수 인터페이스에 맞춰서 전략객체의 기능을 사용하기때문에 매개변수를 위한 준비가 필요합니다그 인터페이스가 많은 서브클래스들을 고려하여 너무 복잡하다면 어떤 서브 객체에게는 쓰이지 않게 되는 매개변수가 생길 수도 있습니다.

후자는 매개변수에 객체 자신의 참조자를 넘겨 처리하는 방법입니다이는 상태패턴과 동일한 방법이라고 하는데요 본객체와 전략객체간의 겹합도가 높아지게 되는 방법이기도 한데 강결합으로해야 효율이 나올 수 밖에 없는 경우외에는 별로임

 

구구단 2 2단노트

 

– 결론-

 

전략패턴은 말그대로 객체의 전략을 런타임에 다르게 설정할 수 있게 해주는 패턴입니다.

객체안의 여러 매서드들에 대한 행동을 무한한 형태로 전략을 조합하여 변경할 수 있습니다.

행동 전체를 변경할 수도 있지만 행동에 쓰이는 알고리즘 하나만 변형하게 하여 성능의

향상을 꾀할 수도있습니다.


예제)

 #include <iostream>

using namespace std;

#define interface struct

interface Manual

{

virtual void Att() = 0;

};


class GunShot :public Manual

{

public : void Att()

{

cout << "따다다다당"<<endl;

}

};


class CanonShot : public Manual

{

public :

void Att()

{

cout <<"푸학 폭~!"<<endl;

}

};


class SteamPack : public Manual

{

public :

void Att()

{

cout <<"따다다다당 따다다다당 따다다다당~!"<<endl;

}

};


class Unit

{

Manual *_strategy;

public :

Unit(Manual *strategy=0)

{

_strategy = strategy;

}

virtual ~Unit() { }

void Att()

{

if(_strategy)

{

_strategy->Att();

}

}

virtual void Display() =0;

};

//*************************Marin*****************************

class Marine :public Unit

{

SteamPack *sp;

public :

Marine(Manual *ma) : Unit(ma)

{

sp = 0;

}

void SteamPackUpGrade()

{

if(sp == 0)

{

sp = new SteamPack();

}

}

void SteamPackAttack()

{

if(sp)

{

sp->Att();

}

}

~Marine()

{

if(sp)

{

delete sp;

}

}

public:

void Display()

{

}

};

//*************************Enginneer*****************************

class Medic :

public Unit

{

public:

Medic(Manual *ma=0) : Unit(ma){ }

public :

void Display()

{

}

};

//*************************Tank*****************************

class Tank:

public Unit

{

public :

Tank(Manual *ma) : Unit(ma) { }

public:

void Display()

{

}

};


void main()

{

Unit *unit = new  Marine(new GunShot);

unit->Att();


Marine *marine = dynamic_cast<Marine*>(unit);

marine->SteamPackUpGrade();

marine->SteamPackAttack();


Unit *unit2 = new  Tank(new CanonShot);

unit2->Att();


Unit *unit3 = new  Medic();

unit3->Att();

delete unit;

delete unit2;

delete unit3;

}


'Programing > Design Pattern' 카테고리의 다른 글

상태패턴 예제  (0) 2016.11.30
State Pattern (상태패턴)  (0) 2016.11.30
템플릿 메서드  (0) 2016.11.30

차량의 뒷모양은 매우 복잡하여서 영상에서도 매우 복잡한 화소 변화로 인해 에지 특징이 잘 나타난다특히 수직 방향의 화소 변화가 두드러지기 때문에 수직 에지 성분이 잘 나타난다.  아래 그림은 수직 에지를 분석한 부분이다.


수직 방향 에지를 분석하여 전체 영역에서 흰색 부분만 추출하기 위해 침식 팽창 연산을 하여 차량 뒷부분을 뚜렷하게 강조 하였다.

 


해당 부분에서 가장 흰색영역이 큰 부분이 우리와 가장 인접한 차량이 된다해당 프로젝트에서 필요한 정보는 앞차와의 거리를 인식하기 위함 이기 때문에 앞차만을 위한 관심 영역을 지정하여 진행 하였다.



이 부분에서 차선을 기반으로 관심영역을 지정해 주면 앞차만을 인식 할 수 있다.


 

 첫번째 결과 이다차량을 정확하게 잡아주기는 하나 앞차선에 대한 관심영역 설정이 잘못되어 앞차량 보다 엣지성분이 많은 트럭을 잡게 되었다.




'Programing > OpenCV' 카테고리의 다른 글

제스쳐 인식  (0) 2016.11.30
제스쳐 인식  (0) 2016.11.30
플러드필  (0) 2016.11.30
Opencv C# 모폴로지  (0) 2016.11.30
영상 모폴로지 자체 커널 만들기  (0) 2016.11.30

+ Recent posts