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

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

#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.3(금) C++ - 단위전략의 기본

from Study/C++ 2007/08/07 21:12 view 14837

// STLstring이 가지고 있는 단위전략패턴의 개념

// STLstring은 문자열의 비교를 위해 단위전략클래스를 사용하고 있다.

// 사용자가 만들어서 전달할수도있다.

 

struct my_traits : public char_traits<char>

{

        // 두문자가 같은 지를 비교하기 위해 아래함수를 호출한다.

        static bool eq(char c1, char c2)
        {
               return toupper(c1) == toupper(c2);
        }

        static bool lt(char c1, char c2)
        {
               return toupper(c1) < toupper(c2);
        }

        static int  compare( const char* s1, const char* s2, size_t n )

        {

               return memicmp( s1, s2, n );

        }

 

        // 그 외의 몇개의 함수를 더 제공해야 한다.

        // 하지만 상속 받았으므로 부모 것을 그냥 사용 할 수도 있다.

};

 

typedef basic_string<char, my_traits, allocator<char> > ci_string;

 

void main()

{

        // 템플릿 인자를 사용하는 단위전략, 함수 단위전략보다 다양한 작업가능.

        // , 컴파일시간에 결정되므로 오버헤드도 줄인다.

        // basic_string<char, my_traits, allocator<char> > s1 = "AA"; 
        //
유니코드, 단위전략, 할당

        ci_string s1 = "hello";

        ci_string s2 = "HELLO";

 

        //string s1 = "hello";

        //string s2 = "HELLO";

 

        if( s1 == s2 )

        {

               cout << "same" << endl;

 

        }

        else

        {

               cout << "NotSame" << endl;

        }

}

Tag | ,

7.31(화) C++ - Composite 패턴

from Study/C++ 2007/08/02 15:53 view 19147

#include <iostream>

#include <string>

#include <vector>

using namespace std;

 

// 폴더와File의공통의부모

class Item

{

        string name;

public:

        Item( string s ) : name ( s ) {}

     
        // 상수함수로만들어야상수함수에서불러올수있다.  

        string GetName() const { return name; }       

 

        virtual int GetSize() = 0;

 

       // Getname을상수함수로만들자!!
       
virtual void print( string prefix ) const
        {

               cout << prefix << GetName() << endl;

        }

};

 

class File : public Item

{

        int size;

public:

        // 부모클래스에디폴트생성자가없으므로명시적으로부모생성자를호출해줘야한다.

        File( string n, int s ) : Item(n), size(s) {}

 

        virtual int GetSize() { return size; }

};

 

class Folder : public Item

{

        vector<Item*> items;

public:

        Folder( string n ) : Item(n) {}

 

        void Add( Item* p ) { items.push_back(p); }

 

        virtual int GetSize()

        {

               int sz = 0;

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

               {

            // 다형성( Polymorphism ), 가상함수를통해객체에따라다른기능을제공한다.

                       sz += items[i]->GetSize();

               }

               return sz;

        }

 

        virtual void print( string prefix ) const

        {

               cout << prefix << GetName() << endl;  // 먼저자신의이름출력

               prefix = prefix + string("\t");

 

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

               {

                       items[i]->print( prefix );

               }

        }

};

 

void main()

{

        Folder* R = new Folder("ROOT");

        Folder* A = new Folder("A");

        Folder* B = new Folder("B");

 

        R->Add(A);

        R->Add(B);

 

        R->Add( new File( "a.txt", 10 ) );

        A->Add( new File( "b.txt", 20 ) );

        B->Add( new File( "c.txt", 30 ) );

 

        cout << R->GetSize() << endl;

 

        R->print("");

}

 

Tag | ,

// 파워포인트 같은 프로그램을 만들고싶다.

// 1. prototype 디자인패턴. - 가상복사생성자

// 2. Template Method 디자인패턴( C++에서는NVI라고도불린다. )

 

// VC2005 에서는반환형을자기로가져도된다. 아래참고

//      virtual Shape* Clone() { return new Circle(*this); }

//      virtual Circle* Clone() { return new Circle(*this); }

 

class Shape

{

public:

        // 자신의 복사본을 만들어내는 가상함수-> 가상복사생성자(prototype 디자인패턴)

        virtual Shape* Clone() { return new Shape(*this); }

 

        // 비가상함수.. public 에가상함수를놓지말자.

        void Draw()

        {

               // 멀티스레드를대비해서동기화객체를얻는다.

               RealDraw();    // 내부구현에서 가상함수를 호출하자.

               //cout << "Shape::Draw" << endl;

               // 동기화 객체를 반납한다.

        }

protected:

        // 모든 가상함수는 protected에 놓자.

        virtual void RealDraw()

        {

               cout << "Shape::Draw" << endl;

        }

};

 

class Rectangle : public Shape

{

public:

        void RealDraw()        { cout << "Rectangle::Draw" << endl; }

 

        virtual Rectangle* Clone() { return new Rectangle(*this); }

};

 

class Circle : public Shape

{

public:

        void RealDraw()        { cout << "Circle::Draw" << endl; }

 

        virtual Circle* Clone() { return new Circle(*this); }

};

 

void main()

{

        Shape* buf[1000];      // 동종의 객체(모든종류의도형)을 보관 할 수 있다.

        int count = 0;

 

        int cmd;

        while ( 1 )

        {

               cin >> cmd;

               if ( cmd == 4 )

               {

                       cout << "몇번째 도형을 복사할까요? >> ";

                       int k;

                       cin >> k;

 

                       buf[count++] = buf[k]->Clone();

               }

               if ( cmd == 1 ) buf[count++] = new Rectangle;

               if ( cmd == 2 ) buf[count++] = new Circle;

               if ( cmd == 3 )

               {

                       for ( int i = 0; i < count; ++i )

                              buf[i]->Draw();       // 다형성을띠게된다.

               }

        }

}

 

Tag | ,