// 책임의 전가- Chain of reponsibility

// MFCVIEW- DOC - FRAME - APP 로 명령을 넘겨주는 것과 같은 원리..

 

#include <iostream>

#include <conio.h>

#include <string>

#include <vector>

using namespace std;

 

// 메뉴를 처리하고 싶은 모든 클래스는 아래 추상클래스에서 상속되어야 한다.

class IMenuHandler

{

       IMenuHandler* next;

public:

       IMenuHandler() : next(0) {}

 

       // 다음 처리할 객체를 지정한다.

       void SetNext( IMenuHandler* p ) { next = p; }

 

    void MenuCommand( int id )

       {

             // 먼저 자신이 처리를 시동한다.

             if ( Resolve( id ) == false ) // 처리를 못한 경우

             {

                    // 다음으로전달
                   
if ( next != 0 ) next->MenuCommand( id );

             }

       }

protected:

       virtual bool Resolve( int id ) = 0;

};

//-------------------------------------------------------

 

#define clrscr()    system("cls")

 

class AbstractMenu

{

       string title;

public:

       AbstractMenu( string s ) : title(s) { }

 

       virtual string GetTitle() const { return title; }

 

       virtual void Command() = 0;   // 순수가상함수- 자식은 꼭 만들어야 한다.

};

 

class PopupMenu : public AbstractMenu

{

       vector<AbstractMenu*> menu_list; // Composite

public:

       PopupMenu(string s) : AbstractMenu(s) { }

 

       void Add( AbstractMenu* p ) { menu_list.push_back( p ); }

       void Remove() { }
 

       virtual string GetTitle() const

       {

             return string("[") + AbstractMenu::GetTitle() + string("]");

       }

 

       // 팝업메뉴가 선택 되었을때를 처리한다.

       virtual void Command()

       {

             while(1)

             {

                    // 화면을 지우고 자신의 하위메뉴를 열거해준다.

                    clrscr();

 

                    for( int i = 0; i < menu_list.size(); ++i )

                    {

                         cout<<i + 1<<"."<< menu_list[i]->GetTitle() <<endl;

                    }

 

                    cout << menu_list.size() + 1 << ". 이전메뉴로" << endl;

                    //-----------------------------------------------

                    int cmd;

                    cout << "메뉴를 생성하세요>> ";

                    cin >> cmd;

 

                    if ( cmd == menu_list.size()+1 ) // 이전메뉴로 선택

                           break;  // 루프탈출해서 자신을 이 함수를  마치고

                                   // 자신을 호출한 부분으로 돌아간다.

                    // 잘못선택한경우

                    if ( cmd <= 0 || cmd > menu_list.size() )    

                           continue;

 

                    // 해당메뉴를 실행한다.

                    menu_list[cmd-1]->Command();

             }

       }

};

 

// 메뉴를 처리하고 싶은 모든 클래스는 아래 인터페이스를 구현해야 한다.

class MenuItem : public AbstractMenu

{

       int id;

       IMenuHandler* pMenuHandler;

public:

       // 부모의 디폴트 생성자가 없으므로 여기서 초기화 해준다.

       MenuItem( string s, int n, IMenuHandler* p )

             : AbstractMenu(s), id(n), pMenuHandler(p) { }

 

       // 메뉴선택시 처리

       virtual void Command()

       {

             if( pMenuHandler != 0 ) pMenuHandler->MenuCommand( id );

       }

};

//------------------------------------------------------

class TapeList : public IMenuHandler

{

public:

       virtual bool Resolve( int id )

       {

             switch( id )

             {

             case 1: foo(); getch(); return true;

             case 2: foo(); getch(); return true;

             }

             return false;

       }

 

       void foo()

       {

             cout << "TapeList::foo" << endl;

       }

};

 

//-----------------------------------------------------

class VideoShop : public IMenuHandler

{

       TapeList tp_list;

 

public:

       void Init()

       {

             PopupMenu* p1 = new PopupMenu("ROOT");

 

             PopupMenu* p2 = new PopupMenu("고객관리");

             PopupMenu* p3 = new PopupMenu("Tape관리");

             PopupMenu* p4 = new PopupMenu("기타");

 

             p1->Add( p2 );

             p1->Add( p3 );

             p1->Add( p4 );

 

             p2->Add( new MenuItem("신규고객등록", 1, this) );

             p2->Add( new MenuItem("고객삭제", 2, this) );

             p2->Add( new MenuItem("기타", 3, this) );

 

             p3->Add( new MenuItem("신규Tape등록", 4, this) );

             p3->Add( new MenuItem("Tape삭제", 5, this) );

             p3->Add( new MenuItem("기타", 6, this) );

 

             // 메뉴를 처리하고 싶은 다음 객체를 등록시킨다.

             this->SetNext( &tp_list );

 

             p1->Command();

       }

 

       void AddCustomer()

       {

             cout << "신규고객등록처리" << endl;

       }

 

       virtual void MenuCommand( int id )

       {

             // 메뉴ID를 가지고 각 함수로 라우팅한다.

             if ( id == 1 ) AddCustomer();

 

             cout << "다른ID처리" << endl;

             getch();

       }

 

       virtual bool Resolve( int id )

       {

             if ( id == 1 )

             {

                    AddCustomer();

                    return true;

             }

             return false;

       }

};

 

 

int main()

{

       VideoShop v;

       v.Init();

}

Tag | ,

#include <iostream>

#include <conio.h>

#include <string>

#include <vector>

using namespace std;

 

#define clrscr()    system("cls")

 

class AbstractMenu

{

       string title;

public:

       AbstractMenu( string s ) : title(s) { }

 

       virtual string GetTitle() const { return title; }

 

       virtual void Command() = 0; // 순수가상함수- 자식은 꼭 만들어야 한다.

};

 

class PopupMenu : public AbstractMenu

{

       vector<AbstractMenu*> menu_list; // Composite

public:

       PopupMenu(string s) : AbstractMenu(s) { }

 

       void Add( AbstractMenu* p ) { menu_list.push_back( p ); }

       void Remove() {}

 

       virtual string GetTitle() const

       {

             return string("[") + AbstractMenu::GetTitle() + string("]");

       }

 

       // 팝업메뉴가 선택 되었을때를 처리한다.

       virtual void Command()

       {

             while(1)

             {

                    // 화면을 지우고 자신의 하위메뉴를 열거 해준다.

                    clrscr();

 

                    for( int i = 0; i < menu_list.size(); ++i )

                    {

                           cout << i + 1 << "." << menu_list[i]->GetTitle() << endl;

                    }

 

                    cout << menu_list.size() + 1 << ". 이전메뉴로" << endl;

                    //---------------------------------------------------------

                    int cmd;

                    cout << "메뉴를생성하세요>> ";

                    cin >> cmd;

 

                    if ( cmd == menu_list.size()+1 ) // 이전메뉴로 선택

                           break;  // 루프 탈출해서 자신을 이함수를 마치고

                                   // 자신을 호출한 부분으로 돌아간다.

                    // 잘못 선택한 경우

                    if ( cmd <= 0 || cmd > menu_list.size() )
                           continue;

 

                    // 해당메뉴를 실행한다.;;

                    menu_list[cmd-1]->Command();

             }

       }

};

 

// 메뉴를 처리하고 싶은 모든 클래스는 아래 인터페이스를 구현해야 한다.

struct IMenuHandler

{

       virtual void MenuCommand( int id ) = 0;

};

 

class MenuItem : public AbstractMenu

{

       int id;

       IMenuHandler* pMenuHandler;

public:

       // 부모의 디폴트 생성자가 없으므로 여기서 초기화 해준다.

       MenuItem( string s, int n, IMenuHandler* p )

             : AbstractMenu(s), id(n), pMenuHandler(p) { }

 

       // 메뉴선택시 처리

       virtual void Command()

       {

             if( pMenuHandler != 0 ) pMenuHandler->MenuCommand( id );

       }

};

//------------------------------------------------------

class VideoShop : public IMenuHandler

{

public:

       void Init()

       {

             PopupMenu* p1 = new PopupMenu("ROOT");

 

             PopupMenu* p2 = new PopupMenu("고객관리");

             PopupMenu* p3 = new PopupMenu("Tape관리");

             PopupMenu* p4 = new PopupMenu("기타");

 

             p1->Add( p2 );

             p1->Add( p3 );

             p1->Add( p4 );

 

             p2->Add( new MenuItem("신규고객등록", 1, this) );

             p2->Add( new MenuItem("고객삭제", 2, this) );

             p2->Add( new MenuItem("기타", 3, this) );

 

             p3->Add( new MenuItem("신규Tape등록", 4, this) );

             p3->Add( new MenuItem("Tape삭제", 5, this) );

             p3->Add( new MenuItem("기타", 6, this) );

 

             p1->Command();

       }

 

       void AddCustomer()

       {

             cout << "신규고객등록처리" << endl;

       }

 

       virtual void MenuCommand( int id )

       {

             // 메뉴ID를 가지고 각 함수로 라우팅한다.

             if ( id == 1 ) AddCustomer();

 

             cout << "다른ID처리" << endl;

             getch();

       }

};

 

 

int main()

{

       VideoShop v;

       v.Init();

}

 

Tag | ,

8.8(수) C++ 디자인패턴 - Callback

from Study/C++ 2007/08/12 19:53 view 24970

// Callback의 개념.


class Car

{

       typedef void(*SIGNAL)();

       SIGNAL signal;

public:

       Car(SIGNAL s = 0) : signal(s) { }

 

       void SpeedUp( int speed )

       {

             cout << "Speed : " << speed << endl;

 

             if( speed > 100 && signal != 0 )

                    signal();    // 외부에알린다.

       }

};

 

void Police()

{

       cout << "Police Start.." << endl;

}

 

void main()

{

       Car c(Police);

 

       c.SpeedUp(100);

       c.SpeedUp(200);

}

/////////////////////////////////////////////////////////////

// 1. callback을 담당 할 클래스를 만들자. - 함수포인터를 관리하는 객체

class delegate

{

       typedef void(*SIGNAL)();

 

       SIGNAL signal;

       vector<delegate*> del_list;

public:

       delegate( SIGNAL s ) : signal(s) {}

 

       void Add( delegate* p ) { del_list.push_back( p ); }

       void Remove( delegate* p ) { }

      

       void Invoke()

       {

             if( signal != 0 ) signal();

 

             for( int i = 0; i < del_list.size(); ++i )

                    del_list[i]->Invoke();

       }

       // 연산자 재정의

       delegate* operator+=(delegate* p)

       {

             Add(p);

             return this;

       }

 

       void operator()()

       {

             Invoke();

       }

};

//----------------------------------------------------------

 

void foo() { cout << "foo" << endl; }

 

void main()

{

       delegate d1(foo);

       delegate d2(foo);

       delegate d3(foo);

 

       d3 += new delegate(foo);

       d3.Add( new delegate(foo) );

 

       d2 += &d3;

       d1.Add( &d2 );

 

       d1.Invoke();

       cout << endl;

       d1();

}

/////////////////////////////////////////////////////////////////
// 2. callback을 담당 할 클래스를 만들자. - 함수포인터를 관리하는 객체

class delegate

{

       typedef void(*SIGNAL)();

 

       SIGNAL signal;

       vector<delegate*> del_list;

public:

       delegate( SIGNAL s ) : signal(s) {}

 

       void Add( delegate* p ) { del_list.push_back( p ); }

       void Remove( delegate* p ) { }

      

       void Invoke()

       {

             if( signal != 0 ) signal();

 

             for( int i = 0; i < del_list.size(); ++i )

                    del_list[i]->Invoke();

       }

       // 연산자재정의

       delegate* operator+=(delegate* p)

       {

             Add(p);

             return this;

       }

 

       void operator()()

       {

             Invoke();

       }

};

//----------------------------------------------------------

class Car

{

public:

       delegate del;

public:

       Car() : del(0) { }

 

       void SpeedUp( int speed )

       {

             cout << "Speed : " << speed << endl;

 

             if( speed > 100  /*&& del != 0*/ )

                    del(); // 외부에알린다.

       }

};

 

void Police()

{

       cout << "Police Start.." << endl;

}

 

void main()

{

       Car c;

 

       c.del += new delegate(Police);

       c.del += new delegate(Police);

 

       c.SpeedUp(100);

       c.SpeedUp(200);

}

 

 

 

 

 

Tag | ,

#include <iostream>

#include <conio.h>

#include <string>

#include <vector>

using namespace std;

 

#define clrscr()       system("cls")

 

class AbstractMenu

{

        string title;

public:

        AbstractMenu( string s ) : title(s) { }

 

        virtual string GetTitle() const { return title; }

 

        virtual void Command() = 0;   // 순수가상함수- 자식은 꼭 만들어야 한다.

};

 

class MenuItem : public AbstractMenu

{

        int id;

public:

        // 부모의 디폴트 생성자가 없으므로 여기서 초기화 해준다.

        MenuItem( string s, int n ) : AbstractMenu(s), id(n) { }    

 

        // 메뉴 선택시 처리

        virtual void Command()

        {

               cout << "MenuItem::Command" << endl;

               getch();

        }

};

 

class PopupMenu : public AbstractMenu

{

        vector<AbstractMenu*> menu_list;      // Composite

public:

        PopupMenu(string s) : AbstractMenu(s) { }

 

        void Add( AbstractMenu* p ) { menu_list.push_back( p ); }

        void Remove() { }      // 나중에 구현.

 

        virtual string GetTitle() const

        {

               return string("[") + AbstractMenu::GetTitle() + string("]");

        }

 

        // 팝업 메뉴가 선택 되었을 때를 처리한다.

        virtual void Command()

        {

               while(1)

               {

                       // 화면을 지우고 자신의 하위메뉴를 열거해준다.

                       clrscr();

 

                       for( int i = 0; i < menu_list.size(); ++i )

                       {

                              cout << i + 1 << "." <<
                                           menu_list[i]->GetTitle() << endl;

                       }

 

                       cout << menu_list.size() + 1 << ". 이전메뉴로" << endl;

                       //-------------------------------------------

                       int cmd;

                       cout << "메뉴를 생성하세요>> ";

                       cin >> cmd;

 

                       if ( cmd == menu_list.size()+1 ) // 이전 메뉴로 선택

                              break; // return; 루프 탈출해서 이함수를 마치고

                                     // 자신을 호출한 부분으로 돌아간다.

 

                       // 잘못 선택한 경우
                      
if ( cmd <= 0 || cmd > menu_list.size() )

                              continue;

 

                       // 해당 메뉴를 실행한다.

                       menu_list[cmd-1]->Command();

               }

        }

};

 

int main()

{

        PopupMenu* p1 = new PopupMenu("ROOT");

 

        PopupMenu* p2 = new PopupMenu("고객관리");

        PopupMenu* p3 = new PopupMenu("Tape관리");

        PopupMenu* p4 = new PopupMenu("기타");

 

        p1->Add( p2 );

        p1->Add( p3 );

        p1->Add( p4 );

 

        p2->Add( new MenuItem("신규고객등록", 1) );

        p2->Add( new MenuItem("고객삭제", 2) );

        p2->Add( new MenuItem("기타", 2) );

 

        p3->Add( new MenuItem("신규Tape등록", 1) );

        p3->Add( new MenuItem("Tape삭제", 2) );

        p3->Add( new MenuItem("기타", 2) );

 

        p1->Command();

}

Tag |

8.7(화) C++ 디자인패턴 - Decorator

from Study/C++ 2007/08/08 20:30 view 21435

바닐라 : 1000

딸기   : 1500

초코   : 2000

 

아몬드 : 300

땅콩   : 200

키위   : 500

 

OCP 기능 확장에는 열려 있고 코드 변경에는 닫혀 있도록 해야 한다.

 

Decorator

 

객체(포장대상) - Item(동일 부모) – 포장지( Item& ) 재귀관점!!

cost() : item.cost() + 자신 // 자신을 꾸며서 리턴하므로 Decorator

 

연결. 데코레이터. 감싸주는것. 감싸서 기능을 합쳐준다.!!!!

아이템을 바꾸는건 전략 패턴..

아이템에 힘을 더해주는건 데코레이터 패턴

비행기를 생산하는건 팩토리 패턴..!!



#include <iostream>

using namespace std;

 

// Decorator 패턴:  객체와 포장을 동일하게 다룬다.

 

// Subject와 포장(Decorator)가 가져야 하는 공통의 인터페이스

struct Item

{

        virtual int cost() = 0;

};

 

// Ice Cream 객체.. 대상(Subject).

class Valina: public Item

{

public:

        virtual int cost() { return 1000; }

};

 

class Strawberry: public Item

{

public:

        virtual int cost() { return 1500; }

};

 

class Choko: public Item

{

public:

        virtual int cost() { return 2000; }

};

//----------------------------------------------------

// Decorator 객체들. 내부적으로 Subject의 참조를 가지고 있다.

 

class Almond : public Item

{

        Item& item;

public:

        Almond( Item& i ) : item(i) { }

 

        virtual int cost()

        {

               return item.cost() + 300;

        }

};

 

class Peanut : public Item

{

        Item& item;

public:

        Peanut( Item& i ) : item(i) { }

 

        virtual int cost()

        {

               return item.cost() + 200;

        }

};

 

class Kiwi : public Item

{

        Item& item;

public:

        Kiwi( Item& i ) : item(i) { }

 

        virtual int cost()

        {

               return item.cost() + 500;

        }

};

 

void main()

{

        Valina ice;

 

        Almond a( ice );

        cout << a.cost() << endl;

 

        Peanut p( a );

        cout << p.cost() << endl;

}

 
////////////////////////////////////////////////////

// Decorator의 예 ..
// MFC에서

void main()

{

        int n = 10;

 

        CFile f( "a.txt", CFile::Create );

 

        f.WriteFile( &n );

 

        CArchive ar( &f, CArchive::store );

        ar << n; // ok.

 

        CSocketFile sf;        // 네트워크

        CArchive( &sf, CArchive::store );

        ar2 >> n;

}

Tag | ,

// OCP에 위반된다. 소스변경을 해야 한다.

// Template Method 라고 불리는 디자인설계

// 1. 전체 알고리즘을 부모에게 둔다.(public, 절대가상이아니다.)

// 2. 알고리즘이 사용하는 세부구현은 가상함수로 만들어서 자식이 구현한다.(protected로구현)

 

class IceCream

{

        bool hasPeanut;

        bool hasAlmond;

        bool hasKiwi;

public:

        IceCream( bool b1, bool b2, bool b3 )

               : hasPeanut(b1), hasAlmond(b2), hasKiwi(b3) {}

 

        int cost()

        {

               int s = IceCost();

 

               if( hasPeanut ) s += 200;

               if( hasAlmond ) s += 300;

               if( hasKiwi )   s += 500;

 

               return s;

        }

 

protected:

        // NVI 가상함수를public으로만들지말자.

        virtual int IceCost() = 0;

};

 

class Vanila : public IceCream

{

public:

        Vanila( bool b1, bool b2, bool b3 ) : IceCream( b1, b2, b3 ) {}

        virtual int IceCost() { return 1000; }

};

 

class Strawberry : public IceCream

{

public:

        Strawberry( bool b1, bool b2, bool b3 ) : IceCream( b1, b2, b3 ) {}

        virtual int IceCost() { return 1500; }

};

 

class Choko : public IceCream

{

public:

        Choko( bool b1, bool b2, bool b3 ) : IceCream( b1, b2, b3 ) {}

        virtual int IceCost() { return 2000; }

};

 

void main()

{

        Choko c1( 1, 1, 0 );

 

        cout << c1.cost() << endl;

}

Tag | ,

#include <iostream>

#include <string>

using namespace std;

 

// 모든 반복자가 가져야 하는 인터페이스를 설계한다. - 실제 C#에는 아래의 interface가 있다.

 

// C# 1.0 에서는 Object 최상위클래스로 받아서 타입캐스팅을 했지만..

// C# 2.0 에서는 Generic의 도입으로 반복자 인터페이스가 편리해졌다.

template<typename T> struct IEnumerator

{

        virtual bool MoveNext() = 0;

        virtual T GetObject() = 0;

        virtual void Reset() = 0;

};

//-------------------------------------------------------

// 또한 반복자를 가질 수 있는 모든 컨테이너는 아래의 인터페이스를 제공해야 한다.

template<typename T> struct IEnumerable

{

        virtual IEnumerator<T>* GetEnumerator() = 0;

};

 

//-------------------------------------------------------

// 열거가능한(반복자를가진) 클래스는 반드시 IEnumerable에서 파생되어야 한다.

template<typename T> class slist : public IEnumerable<T>

{

        struct Node

        {

               T     data;

               Node* next;

 

               Node( T a, Node* n ) : data(a), next(n) {}

        };

 

        Node* head;

public:

        slist() : head(0) {}

 

        void push_back( T a ) { head = new Node( a, head ); }

 

        // slist에서 값을 얻기 위한 반복자

        class SlistEnumerator : public IEnumerator<T>

        {

               Node* current;

               Node* head;

        public:

               SlistEnumerator( Node* init = 0 ) 
               : head(init), current(init) {}

 

               bool MoveNext()

               {

                       current = current->next;

                       return current != 0;

               }

               int  GetObject() { return current->data; }

               void Reset() { current = head; }

        };

 

        //--------------------------------------------------

        // 반복자를 리턴하는 함수를 만든다.

        IEnumerator<T>* GetEnumerator()

        {

               return new SlistEnumerator( head );

        }

};

 

//------------------------------------------------------

// 주어진 반복자를 사용해서 모든 요소의 합을 구한다.

template<typename T> void Sum( IEnumerator<T>* p )

{

        T s = T();

 

        p->Reset();

 

        do

        {

               s += p->GetObject();

        } while ( p->MoveNext() );

 

        cout << s << endl;

}

// 주어진 컨테이너의 모든 요소의 합을 구한다.

template<typename T> void Sum2( IEnumerable<T>& c )

{

        IEnumerator<T>* p = c.GetEnumerator();

        Sum( p );

}

 

int main()

{

        slist<int> s;

 

        s.push_back( 10 );

        s.push_back( 20 );

        s.push_back( 30 );

 

        //IEnumerator<int>* p = s.GetEnumerator();

        //Sum( p );

 

        Sum2( s );

 

        return 0;

}

 

 

Tag |

8.6(월) C++ 디자인패턴 - Factory

from Study/C++ 2007/08/08 20:11 view 20573

#include <iostream>

using namespace std;

 

// factory : 객체 생성을 클래스화 해라.

 

// 도형 편집기를 만들고 싶다.

 

class Shape { };

class Rect : public Shape {};

class Circle : public Shape {};

 

// 이제 도형을 생성하는 공장의 인터페이스를 구현한다.

class IShapeFactory

{

public:

        virtual Shape* CreateShape( char c ) = 0;

};

 

class FactoryVer1 : public IShapeFactory

{

public:

        virtual Shape* CreateShape( char c )

        {

               switch( c )

               {

               case 'C':

                       return new Circle;

               case 'R':

                       return new Rect;

               }

        }

};

 

class FactoryVer2 : public IShapeFactory

{

public:

        virtual Shape* CreateShape( char c )

        {

               switch( c )

               {

               case 'C':

                       return new Circle;

               case 'R':

                       return new Rect;

               case 'T':

                       return new Triangle;   // 확장의 유용성!!

               }

        }

};

 

class Canvas

{

        vector<Shape*> shapes;

        IShapeFactory* factory;

public:

 

        void Save()

        {

        }

        void Load()

        {

               // 어떤 객체인지 표시를 읽어내고, 해당 data를 읽은 후에

               char c = Read();

               char data = Read();

 

               shapes.push_back( factory->CreateShape( c ) ); // 위임한다.

 

               //switch( c )

               //{

               //case 'R':

               //      shapes.push_back( new Rect(data) );

               //      break;

 

               //case 'C':

               //      shapes.push_back( new Circle(data) );

               //      break;

               //}

 

        }

 

        void KeyDown( char c )

        {

               shape.push_back( factory->CreateShape( c ) ); // 위임한다.

 

               //switch( c )

               //{

               //case 'R':

               //      shapes.push_back( new Rect );

               //      break;

               //case 'C':

               //      shapes.push_back( new Circle );

               //      break;

               //}

        }

};

 

Tag | ,

#include <iostream>

using namespace std;

 

// 디자인의 대전제: 모든 코드는 유지보수와 기능확장이 쉽도록 유연하게 설계되어야 한다.

 

// OCP : Open Closed Principle

//       기능확장에 열려있고 코드변경에 닫혀 있어야 한다.

 

// 생각해 볼 만한 문제.. 오목게임을 만들고 싶다. - 1인용.

// 다음 수를 예측하는 알고리즘은 자주 변경 될 수 있을 거 같다.

 

// 1. 변하는 것은 따로 캡슐화를 해라. - 오목과 다음 수 예측알고리즘을 분리한다.

// 2. 상속 대신에 포함을 사용하라. ( 상속은 너무 경직 되어 있다. 떼어다 붙여다가 안된다. )

// 3. 구현이 아닌 인터페이스를 사용해서 객체와 통신해라.( Loosely Coupling )

 

// 결국 아래코드가 GOF의 디자인패턴에 나오는 "전략패턴" 이다.

// 알고리즘(변하는요소를) 캡슐화

// 인터페이스를 먼저 설계한다.

struct IStrategy

{

public:

        virtual void NextPos( int(*p)[19], int* px, int* py ) = 0;

};

 

// 다음 수만 예측하는 알고리즘

class Level1 : public IStrategy

{

public:

        virtual void NextPos( int* px, int* py )

        {

        }

};

 

class Omok

{

        int board[19][19];

        IStrategy* pComputer;  // Composition( 포함, 구성)

public:

        void Run()

        {

               // 컴퓨터에게 다음 수를 두게 한다.

               int x, y;

 

               // Delegation(위임)이라고 부른다.

               pComputer->NextPos( board, &x, &y );

        }

 

        // 동적으로 알고리즘을 변경할 수 있게 한다.

        void SetStrategy( IStrategy* p ) { pComputer = p; }

};

 

void main()

{

}

 

 

/*

// 잘못된 방식

class Omok

{

public:

        virtual void NextPos( int* px, int* py )

        {

        }

};

 

class Level1 : public Omok

{

        virtual void NextPos( int* px, int* py )

        {

        }

};

 

void main()

{

        Omok* p = new Level1;

        p->NextPos();

}

*/

Tag | ,

8.6(월) C++ - STL 알고리즘의 종류

from Study/C++ 2007/08/08 17:29 view 19388

#include <iostream>

#include <algorithm>

#include <numeric>

#include <vector>

#include <functional>

#include <string>

using namespace std;

 

// 알고리즘의종류

// **. 알고림즘의 기본 구성

int foo( int a, int b ); 

 

int main()

{

        int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        int y[10];

 

        int* p1 = remove( x, x+10, 3 );         // 알고리즘의 in place 버전

        int* p2 = remove_copy( x, x+10, y, 3 ); // 알고리즘의 copy 버전

       

        int* p3 = remove_if( x, x+10, foo );  // 알고리즘의 조건자 버전.

        int* p4 = remove_copy_if( x, x+10, y, foo );

 

// sort의 조건자버전- 조건자이름구별..

// sort 같은 알고리즘은 조건자 버전은 인자가 3개이고 조건자를 사용하지 않은 버전은
// 인자가 2개이다. 그러므로 sort함수는 조건자 버전과 그렇지 않은 버전을 명확이 구분
// 할 수 있으므로 _if 가 붙지 않는다!!!
       
sort( x, x+10 );

        sort( x, x+10, foo );

}

 

// sort에사용하는조건자함수규칙

// 아래함수를평가해보세요.

int foo( int a, int b )

{

        //return a <= b;       // 같을때바꾼다는건말도안됨. 1번에어긋남

        return a < b;          // ok.

}

// Strict Weak Ordering ( sort의조건의원칙?? )

// 1) f(a, a)는반드시false여야한다.

// 2) f(a, b)가참이면f(b, a)는거짓이다.

// 3) f(a, b)가참이고f(b, c)가참이면f(a, c)도참이다.

/////////////////////////////////////////////////

// 1. accumulate

void main()

{

        int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

 

        // 기본연산자버전+ 버전

        int n1 = accumulate( x, x+10, 0 );

        cout << n1 << endl;

 

        int n2 = accumulate( x, x+10, 1, multiplies<int>() );

        cout << n2 << endl;

}
/////////////////////////////////////////////////

void main()

{

        int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

 

        int* p1 = find( x, x+10, 3 );      // 변경불가sequence 알고리즘

        int* p2 = remove( x, x+10, 3 );    // 변경가능sequence 알고리즘

 

        sort( x, x+10 );    // 정렬 관련 알고리즘

 

        int n = accumulate( x, x+10, 0 ); // 범용수치알고리즘     "numeric"

        cout << n << endl;

}

// 2. 구간삭제 erase

void main()

{

        int x[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        vector<int> v( x, x+10 );

 

        vector<int>::iterator p = remove( v.begin(), v.end(), 5 );

 

        // v.begin() ~ p까지가 유효한 구간이다. 나머지 유효하지 않은 구간을 지우자!

        v.erase( p, v.end() );

        int n = accumulate( v.begin(), v.end(), 0 );

 

        cout << n << endl;

}

  

// 3. copy, copy_backward

void main()

{

        string s1 = "ABCDE";

 

        // left shift

        //copy( s1.begin() + 1, s1.end(), s1.begin() );

 

        // right shift

        //copy( s1.begin(), s1.end() - 1, s1.begin() + 1 );
        // AAAAA가 출력
뒤에서 부터 copy해야 한다.

 

        copy_backward( s1.begin(), s1.end() - 1, s1.end() );

 

        int x[5] = { 1, 2, 3, 4, 5 };

        int y[5];

 

        //int* p = copy_if( x, x+5, y, foo ); // copy_if가없다. 짜보자!!

 

        cout << s1 << endl;

}

 

// 4. partial_sum

void main()

{

        int x[10] = { 1, 2, 3, 4, 5, -6, 7, 8, 9, 10 };

        int y[10];

 

        // x, x+10 까지의_부분합을구해라.

        partial_sum( x, x+10, y );

        copy( y, y+10, ostream_iterator<int>(cout, " ") );

}

Tag |