2013年9月23日 星期一

裝飾者模式(Decorator Pattern)

裝飾者模式功能在於動態擴充,動態地將責任加諸於物件上。想要擴充功能,裝飾者提供有別於繼承的另一個選擇。

  • 繼承屬於擴充形式之一,但不見得是達到彈性設計的最佳方式。
  • 在我們的設計中,應該允許行為可以被擴充,而無須修改計有的程式碼。
  • 合成與委派可時常在執行時期,動態的加上新的行為。
  • 除了繼承,裝飾者模式也可以讓我們擴充行為。



Decorator 的含意
   f(x) = Decorator(obj)


#include <stdlib.h>
#include <stdio.h>

class CComponent
{
public:
        CComponent()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual ~CComponent()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual int value(void) = 0;
};

class CConcreteComponent : public CComponent
{
private:
        int val;
public:
        CConcreteComponent()
        {
                val = 10;
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual ~CConcreteComponent()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual int value(void)
        {
                printf("%s\n", __PRETTY_FUNCTION__);
                return val;
        }
};

class CDecorator : public CComponent
{
public:
        CDecorator()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual ~CDecorator()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

       //  加上新的行為
        virtual void method(void) = 0;
};

class CConcreteDecoratorA : public CDecorator
{
private:
        CComponent *component;
public:
        CConcreteDecoratorA(CComponent *c) : component(c)
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual ~CConcreteDecoratorA()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
                delete component;
        }

        virtual void method(void)
        {
        }

        // 將原生物件因裝飾後加入新的行為
        virtual int value(void)
        {
                printf("%s\n", __PRETTY_FUNCTION__);
                return 20 + component->value();
        }
};


class CConcreteDecoratorB : public CDecorator
{
private:
        CComponent *component;

public:
        CConcreteDecoratorB(CComponent *c) : component(c)
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual ~CConcreteDecoratorB()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
                delete component;
        }

        virtual void method(void)
        {
        }
       
       // 將原生物件因裝飾後加入新的行為
        virtual int value(void)
        {
                printf("%s\n", __PRETTY_FUNCTION__);
                return 30 + component->value();
        }
};

int main()
{
        CComponent *component = new CConcreteComponent();
        printf("\n");
        component = new CConcreteDecoratorA(component);
        printf("\n");
        component = new CConcreteDecoratorB(component);

        printf("===============================================\n");
        printf("%d\n", component->value());
        printf("===============================================\n");
        delete component;
}

執行結果
CComponent::CComponent()
CConcreteComponent::CConcreteComponent()

CComponent::CComponent()
CDecorator::CDecorator()
CConcreteDecoratorA::CConcreteDecoratorA(CComponent*)

CComponent::CComponent()
CDecorator::CDecorator()
CConcreteDecoratorB::CConcreteDecoratorB(CComponent*)
===============================================
virtual int CConcreteDecoratorB::value()
virtual int CConcreteDecoratorA::value()
virtual int CConcreteComponent::value()
60
===============================================
virtual CConcreteDecoratorB::~CConcreteDecoratorB()
virtual CConcreteDecoratorA::~CConcreteDecoratorA()
virtual CConcreteComponent::~CConcreteComponent()
virtual CComponent::~CComponent()
virtual CDecorator::~CDecorator()
virtual CComponent::~CComponent()
virtual CDecorator::~CDecorator()
virtual CComponent::~CComponent()

在此要思考裝飾者的結構式裡用 delete 是否恰當,原程式是在 Java 上時做,但  C++ 不具備有 garbage collection 的功能。若不再解構式中釋放則會產生 memory leak 的問題。但在另一個 case 裡則會引發錯誤。

使用時機須在思考

int main()
{
        CComponent *component;
        CConcreteComponent concreteComponent;
        printf("\n");
        component = new CConcreteDecoratorA(&concreteComponent);
        printf("\n");
        component = new CConcreteDecoratorB(component);

        printf("===============================================\n");
        printf("%d\n", component->value());
        printf("===============================================\n");
        delete component;
}

CComponent::CComponent()
CConcreteComponent::CConcreteComponent()

CComponent::CComponent()
CDecorator::CDecorator()
CConcreteDecoratorA::CConcreteDecoratorA(CComponent*)

CComponent::CComponent()
CDecorator::CDecorator()
CConcreteDecoratorB::CConcreteDecoratorB(CComponent*)
===============================================
virtual int CConcreteDecoratorB::value()
virtual int CConcreteDecoratorA::value()
virtual int CConcreteComponent::value()
60
===============================================
(執行 delete)
virtual CConcreteDecoratorB::~CConcreteDecoratorB()
virtual CConcreteDecoratorA::~CConcreteDecoratorA()
virtual CConcreteComponent::~CConcreteComponent()
virtual CComponent::~CComponent()
*** Error in `./decorator': double free or corruption (out): 0xbfa397c8 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x767e2)[0xb74ee7e2]
/lib/i386-linux-gnu/libc.so.6(+0x77530)[0xb74ef530]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x1f)[0xb7691b4f]
./decorator[0x8048980]
./decorator[0x8048aec]
./decorator[0x8048b3f]
./decorator[0x8048c10]
./decorator[0x8048c63]
./decorator[0x80487f6]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0xb7491935]
./decorator[0x8048651]
======= Memory map: ========
08048000-0804a000 r-xp 00000000 08:01 393246     /home/archer/src/HeadFirstDesignPatterns/chap03/decorator
0804a000-0804b000 r--p 00001000 08:01 393246     /home/archer/src/HeadFirstDesignPatterns/chap03/decorator
0804b000-0804c000 rw-p 00002000 08:01 393246     /home/archer/src/HeadFirstDesignPatterns/chap03/decorator
0819b000-081bc000 rw-p 00000000 00:00 0          [heap]
b7433000-b7435000 rw-p 00000000 00:00 0 
b7435000-b7476000 r-xp 00000000 08:01 656247     /lib/i386-linux-gnu/libm-2.17.so
b7476000-b7477000 r--p 00040000 08:01 656247     /lib/i386-linux-gnu/libm-2.17.so
b7477000-b7478000 rw-p 00041000 08:01 656247     /lib/i386-linux-gnu/libm-2.17.so
b7478000-b7625000 r-xp 00000000 08:01 656199     /lib/i386-linux-gnu/libc-2.17.so
b7625000-b7627000 r--p 001ad000 08:01 656199     /lib/i386-linux-gnu/libc-2.17.so
b7627000-b7628000 rw-p 001af000 08:01 656199     /lib/i386-linux-gnu/libc-2.17.so
b7628000-b762c000 rw-p 00000000 00:00 0 
b762c000-b7647000 r-xp 00000000 08:01 656224     /lib/i386-linux-gnu/libgcc_s.so.1
b7647000-b7648000 r--p 0001a000 08:01 656224     /lib/i386-linux-gnu/libgcc_s.so.1
b7648000-b7649000 rw-p 0001b000 08:01 656224     /lib/i386-linux-gnu/libgcc_s.so.1
b7649000-b7725000 r-xp 00000000 08:01 1969970    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.17
b7725000-b7726000 ---p 000dc000 08:01 1969970    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.17
b7726000-b772a000 r--p 000dc000 08:01 1969970    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.17
b772a000-b772b000 rw-p 000e0000 08:01 1969970    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.17
b772b000-b7732000 rw-p 00000000 00:00 0 
b7747000-b774b000 rw-p 00000000 00:00 0 
b774b000-b774c000 r-xp 00000000 00:00 0          [vdso]
b774c000-b776c000 r-xp 00000000 08:01 656173     /lib/i386-linux-gnu/ld-2.17.so
b776c000-b776d000 r--p 0001f000 08:01 656173     /lib/i386-linux-gnu/ld-2.17.so
b776d000-b776e000 rw-p 00020000 08:01 656173     /lib/i386-linux-gnu/ld-2.17.so
bfa1a000-bfa3b000 rw-p 00000000 00:00 0          [stack]
Aborted (core dumped)


修改過適合 C++ 的作法

#include <string>
#include <iostream>

using namespace std;

class CComponent
{
public:
        CComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual ~CComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual int value(void) = 0;
        virtual string getInfo(void) = 0;
};

class CConcreteComponent : public CComponent
{
private:
        int val;
public:
        CConcreteComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
                val = 10;
        }

        virtual ~CConcreteComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;

        }

        virtual int value(void)
        {
                return val;
        }

        virtual string getInfo(void)
        {
                return "CConcreteComponent";
        }
};

class CDecorator : public CComponent
{
public:
        CDecorator()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual ~CDecorator()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        // new mothod
        virtual void newMethod(void) = 0;
};

class CConcreteDecoratorA : public CDecorator
{
private:
        CComponent *m_component;
public:
        CConcreteDecoratorA(CComponent *c) : m_component(c)
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual ~CConcreteDecoratorA()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual void newMethod(void)
        {
        }

        // the same mothod but new behavior
        virtual int value(void)
        {
                return 20 + m_component->value();
        }

        virtual string getInfo(void)
        {
                return m_component->getInfo() + " ,CConcreteDecoratorA";
        }
};

class CConcreteDecoratorB : public CDecorator
{
private:
        CComponent *m_component;

public:
        CConcreteDecoratorB(CComponent *c) : m_component(c)
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual ~CConcreteDecoratorB()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual void newMethod(void)
        {
        }

        // the same mothod but new behavior
        virtual int value(void)
        {
                return 30 + m_component->value();
        }

        virtual string getInfo(void)
        {
                return m_component->getInfo() + " ,CConcreteDecoratorA";
        }
};

int main()
{
        CConcreteComponent m;
        cout << endl;

        CConcreteDecoratorA a(&m);

        cout << endl;
        CConcreteDecoratorB b(&a);

        cout << "=============================================" << endl;
        cout << "Info : " << m.getInfo() << endl;
        cout << "Value: " <<m.value() << endl;
        cout << "=============================================" << endl;
        cout << "Info : " << a.getInfo() << endl;
        cout << "Value: " << a.value() << endl;
        cout << "=============================================" << endl;
        cout << "Info : " << b.getInfo() << endl;
        cout << "Value: " << b.value() << endl;
        cout << "=============================================" << endl;
}

修正了動態配置所產生的 memory leak 的問題,但在使用上似乎不能向上例如此彈性。


用 shared_ptr 解決動態配置問題 (only supported by c++11)    
  
#include <string>
#include <iostream>
#include <memory>

using namespace std;

class CComponent
{
public:
        CComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual ~CComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual int value(void) = 0;
        virtual string getInfo(void) = 0;
};

class CConcreteComponent : public CComponent
{
private:
        int val;
public:
        CConcreteComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
                val = 10;
        }

        virtual ~CConcreteComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual int value(void)
        {
                return val;
        }

        virtual string getInfo(void)
        {
                return "CConcreteComponent";
        }
};

class CDecorator : public CComponent
{
public:
        CDecorator()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual ~CDecorator()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        // new mothod
        virtual void newMethod(void) = 0;
};

class CConcreteDecoratorA : public CDecorator
{
private:
        shared_ptr<CComponent> m_component;
public:
        CConcreteDecoratorA(shared_ptr<CComponent> c) : m_component(c)
        {
                cout << __PRETTY_FUNCTION__ << endl;
                cout << "use count:" << c.use_count() << endl;
        }

        virtual ~CConcreteDecoratorA()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual void newMethod(void)
        {
        }

        // the same mothod but new behavior
        virtual int value(void)
        {
                return 20 + m_component->value();
        }

        virtual string getInfo(void)
        {
                return m_component->getInfo() + " ,CConcreteDecoratorA";
        }
};

class CConcreteDecoratorB : public CDecorator
{
private:
        shared_ptr<CComponent> m_component;

public:
        CConcreteDecoratorB(shared_ptr<CComponent> c) : m_component(c)
        {
                cout << __PRETTY_FUNCTION__ << endl;
                cout << "use count:" << c.use_count() << endl;
        }

        virtual ~CConcreteDecoratorB()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual void newMethod(void)
        {
        }

        // the same mothod but new behavior
        virtual int value(void)
        {
                return 30 + m_component->value();
        }

        virtual string getInfo(void)
        {
                return m_component->getInfo() + " ,CConcreteDecoratorA";
        }
};

int main()
{
        shared_ptr<CComponent> m(new CConcreteComponent());
        cout << "m's use count:" << m.use_count() << endl;
        cout << endl;

        shared_ptr<CComponent> a(new CConcreteDecoratorA(m));
        cout << "a's use count:" << a.use_count() << endl;
        cout << endl;

        shared_ptr<CComponent> b(new CConcreteDecoratorB(m));
        cout << "b's use count:" << b.use_count() << endl;

        cout << "=============================================" << endl;
        cout << "Info : " << m->getInfo() << endl;
        cout << "Value: " << m->value() << endl;
        cout << "=============================================" << endl;
        cout << "Info : " << a->getInfo() << endl;
        cout << "Value: " << a->value() << endl;
        cout << "=============================================" << endl;
        cout << "Info : " << b->getInfo() << endl;
        cout << "Value: " << b->value() << endl;
        cout << "=============================================" << endl;
}
                     

2013年9月15日 星期日

XBMC used strategy pattern to implement player to playback file.

XBMC 使用 Strategy pattern 實作 player,各 player 實作 IPlayer 介面,提供控制方法由 CApplication 控制

在執行時期由 CPlayerCoreFactory::Get().CreatePlayer(eNewCore, *this)
動態決定要掛載的 player 實體


bool CApplication::PlayFile(const CFileItem& item, bool bRestart)
{
     :
     :
  if (!m_pPlayer)
  {
    m_eCurrentPlayer = eNewCore;
    m_pPlayer = CPlayerCoreFactory::Get().CreatePlayer(eNewCore, *this);
  }
:
     :
}

if __name__ == "__main__"

在 python 裡 __name__ 可用來識別當下所執行 module 名稱
讓我們來看以下幾個範例

# file: test1.py
print "the module name is:", __name__


#file: test2.py
print "the module name is:", __name__


#file: test3.py
import test1
import test2
print "the module name is:", __name__

分別執行 test1.py test2.py test3.py 可到如下結果


#>: python test1.py
the module name is: __main__

#>: python test2.py
the module name is: __main__

#>: python test3.py
the module name is: test1
the module name is: test2
the module name is: __main__

我們可以知道,在當下執行的檔案 __name__ 會是 "__main__",若被 import 到其他檔案中被執行到則 __name__ 會是該 module 的名稱,可由執行 test3.py 驗證.

由於 python 是直譯是語言,interpreter 再載入各 module 時同時也會直行該 module 所包含的程式碼.若要避免不必要地誤動作可在各 module 內加入 if __name__ == "__main__",避免程式碼被執行.

我們可將上述檔案改變如下,並觀察執行結果,則可發現在執行 test3.py 的時候可避開 test1.py
與  test2.py 載入時不必要的執行.

# file: test1.py
if __name__ == "__main__":
    print "the module name is:", __name__


#file: test2.py
if __name__ == "__main__":
    print "the module name is:", __name__


#file: test3.py
import test1
import test2

if __name__ == "__main__":
    print "the module name is:", __name__

#>: python test1.py:
the module name is: __main__

#>: python test2.py
the module name is: __main__

#>: python test3.py
the module name is: __main__

2013年9月14日 星期六

Mplayer backend example





#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <string>


using namespace std;

int main()
{
        int   pipefd[2] = {0};

        if(pipe(pipefd) != 0) {
                printf("pipe open failed\n");
        }

        if(fork() != 0) {
                string command;
                close(pipefd[0]);

                while(1) {
                        cout << "command:";
                        cin >> command;
                        command += "\n";

                        write(pipefd[1], command.c_str(), command.length());

                }
        } else {
                dup2(pipefd[0], fileno(stdin));

                execl("/usr/bin/mplayer", "mplayer",
                      "-slave", "-fs", "-osdlevel", "0", "-really-quiet",
                      "-input", "nodefault-bindings", "-noconfig", "all",
                      "/home/archer/Videos/300_Trailer2_8mbps_1080p29.98_5.1.wmv", NULL);
        }

        return 0;
}

2013年9月13日 星期五

Observer Model example for C++


  • Observer Model
    • The Observer dose not actively to get the data from the Subject else the Subject will
      notify the Observer when there are something changed.
    • 觀察者模式定義了物件之間一對多的關係
    • 主題(Subject) 更新觀察者的方式 ,是透過一個共用介面。
    • 觀察者與可觀察者之間採用鬆綁的方式結合(loose-coupling),因為可觀察者不知道觀察者的細節,只知道觀察者有實踐特定的觀察者介面。




#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <list>

using namespace std;

class CObserver
{
public:
        virtual void update(int data) = 0;
};

class CSubject
{
public:
        virtual void registerObserver(CObserver *obs) = 0;
        virtual void deleteObserver(CObserver *obs) = 0;
        virtual void notify(void) = 0;
};

class CInformationStation : public CSubject
{
private:
        list<CObserver *> m_observerList;
public:
        virtual void registerObserver(CObserver *obs);
        virtual void deleteObserver(CObserver *obs);
        virtual void notify(void);
};

void CInformationStation::registerObserver(CObserver *obs)
{
        list<CObserver *>::iterator it;
        bool found = false;

        for(it = m_observerList.begin(); it != m_observerList.end(); it++) {
                if(*it == obs){
                        found = true;
                        break;
                }
        }

        if(!found)
                m_observerList.push_back(obs);
}

void CInformationStation::deleteObserver(CObserver *obs)
{
        list<CObserver *>::iterator it;

        for(it = m_observerList.begin(); it != m_observerList.end(); it++) {
                if(*it == obs) {
                        m_observerList.erase(it);
                        break;
                }
        }
}

void CInformationStation::notify(void)
{
        list<CObserver *>::iterator it;

        for(it = m_observerList.begin(); it != m_observerList.end(); it++) {
                srand((int)time(0));
                sleep(1);
                (*it)->update( rand() % 1000);
        }
}

class CStatistic : public CObserver
{
private:
        int m_data;
public:
        CStatistic() : m_data(0) {}

        virtual void update(int data)
        {
                m_data = data;
        }

        void display(void)
        {
                printf("[%s] m_data:%d\n", __PRETTY_FUNCTION__, m_data);
        }
};

int main()
{
        CInformationStation station;
        CStatistic statistic1, statistic2, statistic3;

        station.registerObserver(&statistic1);
        station.registerObserver(&statistic2);
        station.registerObserver(&statistic3);

        station.notify();

        statistic1.display();
        statistic2.display();
        statistic3.display();

        return 0;
}

2013年9月12日 星期四

Call by reference of const object argument passing.

當 function 或 member 透過 call by reference 傳遞參數時有個有趣的現象,如下範例

#include <stdlib.h>
#include <stdio.h>
#include <string>

using namespace std;

class CFoo
{
public:
    CFoo(strring &str)
    {
        printf("[%s]: str:%p\n", __PRETTY_FUNCTION__, &str);
    }

    CFoo(int &i)
    {
        printf("[%s]: i:%p\n", __PRETTY_FUNCTION__, &i);
    }
    CFoo(CFoo &foo)
    {
        printf("[%s]: foo:%p\n", __PRETTY_FUNCTION__, &foo);
    }
    ~CFoo()
    {
       printf("[%s]\n", __PRETTY_FUNCTION__);
    }
};

void func1(const CFoo &foo)
{
    printf("[%s]: foo:%p\n", __PRETTY_FUNCTION__, &foo);
}

//void func2(CFoo &foo)
//{
//    printf("[%s]: foo:%p\n", __PRETTY_FUNCTION__, &foo);
//}

int main()
{
    CFoo foo;
    string str = "str";
    int i = 10;

    printf("&foo:%p\n", &foo);
    func1(foo);

    printf("&str:%p\n", &str);
    func1(str);

    printf("&i:%p\n", & i);
    func1(i);

    return 0;
}

當 g++ 面對不同型態的參數呼叫 func1() 時 , 除了 func1(foo) 之外, 都會暫時產生一個 CFoo 的object 並依照其 CFoo 所定義的 constructor 完成 func1 參數裡的物件建構.但只限 const object.

如果將 func1() 替換成 func2(),則除了 func2(foo) 可順利編譯成功, 其他方式的呼叫皆會在 compiling time 時出現錯誤.因為 compiler 並不會為其他呼叫方式產生臨時的 instance, 所以將會有型別不符的錯誤.

void func1(const CFoo &foo)void func2(CFoo &foo) 除了 const 修飾詞所表示的不可修改之外,在參數傳遞的建構方式也有所不同.



2013年9月9日 星期一

Designed Patterns


  • 模式不是程式碼,而是針對特定系統的解決方案,是解決程式中設計的問題。
  • 模式不是被發明,而是被發現。
  • 我門通常把系統中,會變動的部分抽出來封裝。
  • 利用繼承設計次類別的行為,是在編譯時期靜態決定的,而且所以次類別都會繼承到相同的行為。
  • 利用合成的作法擴充物件的行為,就可以在執行時期動態地進行擴充。

(Head First Design Patterns) Strategy Patten


  • 多用合成 ,少用繼承 (More composition less inheritance)
    • 使用合成建立系統具有很大的彈性,不僅可以將演算法封裝成類別,更可以在執行期動態改變行為,只要合成的行為物件,符合特定的介面標準即可。
E.X:

#include <stdlib.h>
#include <stdio.h>

// particular interface
class IFlyBehavior
{
public:
        virtual void fly(void) = 0;
};

// The interface implementance 
class CFlyWithWings : public IFlyBehavior
{
public:
        virtual void fly(void)
        {
                printf("I'm flying\n");
        }
};

// The interface implementance 
class CFlyNoWay : public IFlyBehavior
{
public:
        virtual void fly(void)
        {
                printf("I can't fly\n");
        }
};

// particular interface
class IQuackBehavior
{
public:
        virtual void quack(void) = 0;
};

// The interface implementance 
class CQuack : public IQuackBehavior
{
public:
        virtual void quack(void)
        {
                printf("Quick\n");
        }
};

// The interface implementance 
class CMuteQuack : public IQuackBehavior
{
public:
        virtual void quack(void)
        {
                printf("<<silence>>\n");
        }
};

class Squeak : public IQuackBehavior
{
public:
        virtual void quack(void)
        {
                printf("Squeak\n");
        }
};

class CDuck
{
protected:
        IFlyBehavior *m_flyBehavior;             // more fixable
        IQuackBehavior *m_quackBehavior;  // more fixable
public:
        CDuck(){}
        virtual ~CDuck(){}
        virtual void display() = 0;

        virtual void performQuack(void)
        {
                m_quackBehavior->quack();
        }

        virtual void performFly(void)
        {
                m_flyBehavior->fly();
        }

        virtual void swim()
        {
                printf("All duck float, even decoys!");
        }
};

class CMallardDuck : public CDuck
{
public:
        CMallardDuck()
        {
                m_flyBehavior = new CFlyWithWings(); // can be replacement at runtime
                m_quackBehavior = new CQuack();        
        }
        virtual ~CMallardDuck()
        {
                delete m_flyBehavior;
                delete m_quackBehavior;
        }

        virtual void display(void)
        {
        }
};

int main()
{
        CDuck &mallard =  *(new CMallardDuck());

        mallard.performQuack();
        mallard.performFly();

        return 0;
}