Текущая версия |
Ваш текст |
Строка 308: |
Строка 308: |
| | | |
| == Создатель экземпляров класса (Creator) == | | == Создатель экземпляров класса (Creator) == |
- | <source lang="cpp">template <typename TItem>
| |
- | class CDataStorage
| |
- | {
| |
- | private:
| |
- | std::vector<TItem*> m_items;
| |
- |
| |
- | public:
| |
- | CDataStorage () {};
| |
- | ~CDataStorage ()
| |
- | {
| |
- | for (auto it = m_items.begin (); it != m_items.end(); ++it)
| |
- | delete *it;
| |
- | }
| |
- |
| |
- | std::size_t createItem ()
| |
- | {
| |
- | std::size_t item_index = m_items.size ();
| |
- | m_items.push_back (new TItem());
| |
- | return item_index;
| |
- | }
| |
- |
| |
- | std::size_t size () const { return m_items.size ();}
| |
- | TItem & itemAt (std::size_t index) { return *m_items[index];}
| |
- | const TItem & itemAt (std::size_t index) const { return *m_items[index];}
| |
- | };
| |
- |
| |
- | int main(int argc, char* argv[])
| |
- | {
| |
- | CDataStorage<int> data;
| |
- | data.createItem ();
| |
- | data.createItem ();
| |
- | int &item1 = data.itemAt (0);
| |
- | item1 = 42;
| |
- | std::cout << data.itemAt (0);
| |
- | }</source>
| |
- |
| |
| == Строитель (Builder) == | | == Строитель (Builder) == |
| <source lang="cpp">#include <string> | | <source lang="cpp">#include <string> |
Строка 497: |
Строка 461: |
| = Структурные паттерны проектирования классов/обьектов = | | = Структурные паттерны проектирования классов/обьектов = |
| == Адаптер (Adapter) == | | == Адаптер (Adapter) == |
- | <source lang="cpp">class CDisplay {
| |
- | public:
| |
- | void drawMessage (int x, int y, const std::string &message)
| |
- | {
| |
- | std::cout << "Display at " << x << " " << y << ": " << message << std::endl;
| |
- | }
| |
- | int width () { return 200; }
| |
- | int height () { return 100; }
| |
- | };
| |
- |
| |
- | class CDisplayAdapter {
| |
- | private:
| |
- | CDisplay *m_pDisplay;
| |
- | public:
| |
- | CDisplayAdapter (CDisplay *display) { m_pDisplay = display;}
| |
- | void message (float x, float y, const std::string &message)
| |
- | {
| |
- | int display_x = x * m_pDisplay->width ();
| |
- | int display_y = y * m_pDisplay->height ();
| |
- | m_pDisplay->drawMessage (display_x, display_y, message);
| |
- | }
| |
- | };
| |
- |
| |
- | int main(int argc, char* argv[])
| |
- | {
| |
- | CDisplay *output = new CDisplay ();
| |
- | CDisplayAdapter display_adapter (output);
| |
- |
| |
- | display_adapter.message (0.5f, 0.5f, "I'm center!");
| |
- | }</source>
| |
- |
| |
| == Декоратор (Decorator) или Оболочка (Wrapper) == | | == Декоратор (Decorator) или Оболочка (Wrapper) == |
- | Предназначен для динамического расширения функциональности объекта (добавления дополнительного поведения).
| |
- | <source lang=cpp>
| |
- | #include <iostream>
| |
- |
| |
- | class CWidget
| |
- | {
| |
- | public:
| |
- | virtual void draw() = 0;
| |
- | };
| |
- |
| |
- | class CDialog : public CWidget
| |
- | {
| |
- | public:
| |
- | void draw(){ std::cout << "Draw CDialog" << std::endl; }
| |
- | };
| |
- |
| |
- | class CToolBar : public CWidget
| |
- | {
| |
- | CWidget *m_pWrap;
| |
- | public:
| |
- | CToolBar( CWidget *pWrap ): m_pWrap(pWrap){}
| |
- | void draw(){ std::cout << "Draw CToolBar" << std::endl; m_pWrap->draw(); }
| |
- | };
| |
- |
| |
- | class CStatusBar : public CWidget
| |
- | {
| |
- | CWidget *m_pWrap;
| |
- | public:
| |
- | CStatusBar( CWidget *pWrap ): m_pWrap(pWrap){}
| |
- | void draw(){ m_pWrap->draw(); std::cout << "Draw CStatusBar" << std::endl; }
| |
- | };
| |
- |
| |
- | int main( int argc, char **argv)
| |
- | {
| |
- | CWidget *pDlg = new CDialog(); // Диалог без тулбара и статусбара
| |
- | pDlg->draw();
| |
- |
| |
- | std::cout << std::endl;
| |
- |
| |
- | CWidget *pDlgT = new CToolBar( new CDialog() ); // Диалог c тулбаром и без статусбара
| |
- | pDlgT->draw();
| |
- |
| |
- | std::cout << std::endl;
| |
- |
| |
- | CWidget *pDlgTS = new CToolBar( new CStatusBar( new CDialog() ) ); // Диалог c тулбаром и c статусбаром
| |
- | pDlgTS->draw();
| |
- |
| |
- | return 0;
| |
- | }
| |
- | </source>
| |
- | где, CToolBar и CStatusBar являются декораторами.
| |
- |
| |
- | Результат:
| |
- | <source lang=bash>
| |
- | Draw CDialog
| |
- |
| |
- | Draw CToolBar
| |
- | Draw CDialog
| |
- |
| |
- | Draw CToolBar
| |
- | Draw CDialog
| |
- | Draw CStatusBar
| |
- | </source>
| |
- |
| |
| == Заместитель (Proxy) или Суррогат (Surrogate) == | | == Заместитель (Proxy) или Суррогат (Surrogate) == |
- | Контролирует доступ к другому объекту, перехватывая все вызовы.
| |
- | <source lang=cpp>
| |
- | #include <iostream>
| |
- | #include <string>
| |
- |
| |
- | class CImage
| |
- | {
| |
- | std::string m_szName;
| |
- | public:
| |
- | CImage(std::string szName):m_szName(szName){}
| |
- | void draw(){ std::cout << "Drawing image: " << m_szName << std::endl; }
| |
- | void printName()const { std::cout << "CImage::printName" << std::endl; }
| |
- | };
| |
- |
| |
- | class CProxyImage
| |
- | {
| |
- | CImage *m_pImage;
| |
- | std::string m_szName;
| |
- | public:
| |
- | CProxyImage( std::string szName): m_pImage(0), m_szName(szName){}
| |
- | void draw()
| |
- | {
| |
- | if( !m_pImage )
| |
- | m_pImage = new CImage(m_szName);
| |
- | m_pImage->draw();
| |
- | }
| |
- | void printName()const
| |
- | {
| |
- | if( m_pImage )
| |
- | {
| |
- | m_pImage->printName();
| |
- | return;
| |
- | }
| |
- | std::cout << "CProxyImage::printName" << std::endl;
| |
- | }
| |
- | };
| |
- |
| |
- | int main( int argc, char **argv)
| |
- | {
| |
- | CProxyImage image( "testImage.png" );
| |
- | image.printName();
| |
- | image.draw();
| |
- | image.printName();
| |
- |
| |
- | return 0;
| |
- | }</source>В роли прокси тут выступает CProxyImage, который пока не вызван метод рисования картинки обрабатывает все запросы.
| |
- |
| |
- | Результат:
| |
- | <source lang=bash>CProxyImage::printName
| |
- | Drawing image: testImage.png
| |
- | CImage::printName</source>
| |
- |
| |
| == Информационный эксперт (Information Expert) == | | == Информационный эксперт (Information Expert) == |
| == Компоновщик (Composite) == | | == Компоновщик (Composite) == |
- | <source lang="cpp">class CDrawable {
| |
- | public:
| |
- | CDrawable () {};
| |
- | virtual ~CDrawable () {};
| |
- |
| |
- | virtual void draw () = 0;
| |
- | };
| |
- |
| |
- | class CCircle : public CDrawable {
| |
- | public:
| |
- | virtual void draw () { std::cout << "I'm a circle!" << std::endl;}
| |
- | };
| |
- |
| |
- | class CRectangle : public CDrawable {
| |
- | public:
| |
- | virtual void draw () { std::cout << "I'm a rectangle!" << std::endl;}
| |
- | };
| |
- |
| |
- | class CDrawableGroup : public CDrawable {
| |
- | private:
| |
- | std::list<CDrawable*> m_children;
| |
- | public:
| |
- | CDrawableGroup () {};
| |
- | virtual ~CDrawableGroup ()
| |
- | {
| |
- | while (!m_children.empty ()) {
| |
- | delete m_children.back ();
| |
- | m_children.pop_back ();
| |
- | };
| |
- | };
| |
- |
| |
- | void addChild (CDrawable *drawable) { m_children.push_back (drawable); };
| |
- | void removeChild (CDrawable *drawable)
| |
- | {
| |
- | m_children.remove (drawable);
| |
- | delete drawable;
| |
- | };
| |
- |
| |
- | virtual void draw () {
| |
- | for (auto it = m_children.begin (); it != m_children.end (); ++it)
| |
- | (*it)->draw ();
| |
- | };
| |
- | };
| |
- |
| |
- | int main(int argc, char* argv[])
| |
- | {
| |
- | CDrawableGroup figures;
| |
- | figures.addChild (new CCircle ());
| |
- |
| |
- | CDrawableGroup *rect_group = new CDrawableGroup ();
| |
- | rect_group->addChild (new CRectangle ());
| |
- | rect_group->addChild (new CRectangle ());
| |
- | figures.addChild (rect_group);
| |
- | figures.draw ();
| |
- | }</source>
| |
- |
| |
| == Мост (Bridge), Handle (описатель) или Тело (Body) == | | == Мост (Bridge), Handle (описатель) или Тело (Body) == |
- | <source lang="cpp"> | + | <source language="cpp"> |
| #include <iostream> | | #include <iostream> |
| | | |
Строка 784: |
Строка 545: |
| == Команда (Command), Действие (Action) или Транзакция (Транзакция) == | | == Команда (Command), Действие (Action) или Транзакция (Транзакция) == |
| == Наблюдатель (Observer), Опубликовать - подписаться (Publish - Subscribe) или Delegation Event Model == | | == Наблюдатель (Observer), Опубликовать - подписаться (Publish - Subscribe) или Delegation Event Model == |
- | <source lang="cpp">
| |
- | #include <iostream>
| |
- | #include <vector>
| |
- | #include <algorithm>
| |
- |
| |
- | class CObserver;
| |
- |
| |
- | class CModel
| |
- | {
| |
- | std::vector<CObserver*> m_views;
| |
- | int m_nValue;
| |
- | public:
| |
- | void attach(CObserver *po) { m_views.push_back( po ); }
| |
- | void detach(CObserver *po)
| |
- | {
| |
- | std::vector<CObserver*>::iterator iter = std::find( m_views.begin(), m_views.end(), po);
| |
- | if( iter != m_views.end() )
| |
- | {
| |
- | m_views.erase( iter );
| |
- | }
| |
- | }
| |
- | void setValue(int val)
| |
- | {
| |
- | m_nValue = val;
| |
- | notify();
| |
- | }
| |
- | int getValue() { return m_nValue; }
| |
- | void notify();
| |
- | };
| |
- |
| |
- | class CObserver
| |
- | {
| |
- | CModel *m_pModel;
| |
- | public:
| |
- | CObserver(CModel *pMod)
| |
- | {
| |
- | m_pModel = pMod;
| |
- | m_pModel->attach(this);
| |
- | }
| |
- |
| |
- | virtual ~CObserver()
| |
- | {
| |
- | m_pModel.detach(this);
| |
- | }
| |
- |
| |
- | virtual void update() = 0;
| |
- | protected:
| |
- | CModel *getModel() { return m_pModel; }
| |
- | };
| |
- |
| |
- | class CViewDiagram: public CObserver
| |
- | {
| |
- | public:
| |
- | CViewDiagram(CModel *pMod): CObserver(pMod){}
| |
- | void update() { std::cout << "CViewDiagram: " << getModel()->getValue() << std::endl; }
| |
- | };
| |
- |
| |
- | class CViewDocument: public CObserver
| |
- | {
| |
- | public:
| |
- | CViewDocument(CModel *pMod): CObserver(pMod){}
| |
- | void update() { std::cout << "CViewDocument: " << getModel()->getValue() << std::endl; }
| |
- | };
| |
- |
| |
- | void CModel::notify()
| |
- | {
| |
- | for (size_t i = 0; i < m_views.size(); i++)
| |
- | m_views[i]->update();
| |
- | }
| |
- |
| |
- | int main()
| |
- | {
| |
- | CModel model;
| |
- | CViewDocument doc( &model );
| |
- | CViewDiagram diagr( &model );
| |
- |
| |
- | for( int n= 0; n < 10; ++n)
| |
- | {
| |
- | model.setValue( n );
| |
- | if( n ==5 )
| |
- | model.detach( &diagr );
| |
- | }
| |
- | }</source>В роли CObserver в данном примере выступают классы виды: CViewDiagram с CViewDocument. Они получают уведомления об изменении в модели.
| |
- | Вывод:
| |
- | <source lang="cpp">CViewDocument: 0
| |
- | CViewDiagram: 0
| |
- | CViewDocument: 1
| |
- | CViewDiagram: 1
| |
- | CViewDocument: 2
| |
- | CViewDiagram: 2
| |
- | CViewDocument: 3
| |
- | CViewDiagram: 3
| |
- | CViewDocument: 4
| |
- | CViewDiagram: 4
| |
- | CViewDocument: 5
| |
- | CViewDiagram: 5
| |
- | CViewDocument: 6
| |
- | CViewDocument: 7
| |
- | CViewDocument: 8
| |
- | CViewDocument: 9</source>
| |
- |
| |
| == Не разговаривайте с неизвестными (Don't talk to strangers) == | | == Не разговаривайте с неизвестными (Don't talk to strangers) == |
| == Посетитель (Visitor) == | | == Посетитель (Visitor) == |
| == Посредник (Mediator) == | | == Посредник (Mediator) == |
| == Состояние (State) == | | == Состояние (State) == |
- | <source lang="cpp">#include <iostream>
| |
- |
| |
- | class CSocket;
| |
- | class CStateOpen;
| |
- | class CStateRead;
| |
- | class CStateClose;
| |
- |
| |
- | class CState
| |
- | {
| |
- | public:
| |
- | virtual ~CState() {}
| |
- |
| |
- | virtual void open(CSocket *s) { std::cout << "Already open socket" << std::endl; }
| |
- | virtual void read(CSocket *s) { std::cout << "Already read socket" << std::endl; }
| |
- | virtual void close(CSocket *s) { std::cout << "Already close socket" << std::endl; }
| |
- | };
| |
- |
| |
- | class CSocket
| |
- | {
| |
- | CState *m_pCurrentState;
| |
- | public:
| |
- | CSocket();
| |
- | void setCurrent(CState *p){ m_pCurrentState = p; }
| |
- | void open() { m_pCurrentState->open(this); }
| |
- | void read() { m_pCurrentState->read(this); }
| |
- | void close() { m_pCurrentState->close(this); }
| |
- | };
| |
- |
| |
- | class CStateOpen: public CState
| |
- | {
| |
- | public:
| |
- | CStateOpen(){ std::cout << " CStateOpen" << std::endl; }
| |
- | ~CStateOpen(){ std::cout << " ~CStateOpen" << std::endl; }
| |
- | virtual void read(CSocket *s);
| |
- | virtual void close(CSocket *s);
| |
- | };
| |
- |
| |
- | class CStateRead: public CState
| |
- | {
| |
- | public:
| |
- | CStateRead(){ std::cout << " CStateRead" << std::endl; }
| |
- | ~CStateRead(){ std::cout << " ~CStateRead" << std::endl; }
| |
- | virtual void open(CSocket *s) { std::cout << " Socket already open..." << std::endl; }
| |
- | virtual void close(CSocket *s);
| |
- | };
| |
- |
| |
- | class CStateClose: public CState
| |
- | {
| |
- | public:
| |
- | CStateClose(){ std::cout << " CStateClose" << std::endl; }
| |
- | ~CStateClose(){ std::cout << " ~CStateClose" << std::endl; }
| |
- | virtual void open(CSocket *s)
| |
- | {
| |
- | std::cout << " Open closing socket" << std::endl;
| |
- | s->setCurrent( new CStateOpen());
| |
- | }
| |
- | virtual void read(CSocket *s) { std::cout << " Error: Don't read closing socket" << std::endl; }
| |
- | };
| |
- |
| |
- | CSocket::CSocket()
| |
- | {
| |
- | m_pCurrentState = new CStateClose();
| |
- | }
| |
- |
| |
- | void CStateOpen::read(CSocket *s)
| |
- | {
| |
- | std::cout << " Read socket" << std::endl;
| |
- | s->setCurrent( new CStateRead());
| |
- | }
| |
- | void CStateOpen::close(CSocket *s)
| |
- | {
| |
- | std::cout << " Close socket after opening" << std::endl;
| |
- | s->setCurrent( new CStateClose());
| |
- | }
| |
- |
| |
- | void CStateRead::close(CSocket *s)
| |
- | {
| |
- | std::cout << " Close socket after reading" << std::endl;
| |
- | s->setCurrent( new CStateClose());
| |
- | }
| |
- |
| |
- | int main()
| |
- | {
| |
- | void(CSocket::*ptrs[])() = { &CSocket::open, &CSocket::read, &CSocket::close };
| |
- | CSocket sock;
| |
- | int num;
| |
- | while( 1 )
| |
- | {
| |
- | std::cout << "Enter 0/2: ";
| |
- | std::cin >> num;
| |
- | (sock.*ptrs[num])();
| |
- | }
| |
- | }</source>В данном случае классами состояния являются: CStateOpen, CStateRead и CStateClose. Которые в случае того или иного действия с сокетом меняются...
| |
- | <source lang="bash"> CStateClose
| |
- | Enter 0/2: 0
| |
- | Open closing socket
| |
- | CStateOpen
| |
- | Enter 0/2: 1
| |
- | Read socket
| |
- | CStateRead
| |
- | Enter 0/2: 2
| |
- | Close socket after reading
| |
- | CStateClose
| |
- | Enter 0/2: 0
| |
- | Open closing socket
| |
- | CStateOpen
| |
- | Enter 0/2: 2
| |
- | Close socket after opening
| |
- | CStateClose
| |
- | Enter 0/2: 1
| |
- | Error: Don't read closing socket
| |
- | </source>
| |
- |
| |
| == Стратегия (Strategy) == | | == Стратегия (Strategy) == |
| == Хранитель (Memento) == | | == Хранитель (Memento) == |
| == Цепочка обязанностей (Chain of Responsibility) == | | == Цепочка обязанностей (Chain of Responsibility) == |
| == Шаблонный метод (Template Method) == | | == Шаблонный метод (Template Method) == |
- | <source lang="cpp">#include <iostream>
| |
- |
| |
- | class CApp
| |
- | {
| |
- | public:
| |
- | void openDocument()
| |
- | {
| |
- | //...
| |
- | doOpenDocument();
| |
- | //...
| |
- | }
| |
- |
| |
- | protected:
| |
- | virtual void doOpenDocument() { std::cout << "Open simple document" << std::endl; }
| |
- | };
| |
- |
| |
- | class CXmlApp: public CApp
| |
- | {
| |
- | protected:
| |
- | void doOpenDocument() { std::cout << "Open XML document" << std::endl; }
| |
- | };
| |
- |
| |
- | class CTxtApp: public CApp
| |
- | {
| |
- | protected:
| |
- | void doOpenDocument() { std::cout << "Open TXT document" << std::endl; }
| |
- | };
| |
- |
| |
- | int main()
| |
- | {
| |
- | CApp *pApps[] = { &CApp(), &CXmlApp(), &CTxtApp() };
| |
- | for( int n = 0; n < 3; ++n )
| |
- | pApps[n]->openDocument();
| |
- | return 0;
| |
- | }</source>В данном примере метод doOpenDocument является шаблонным методом.
| |
- | Вывод:
| |
- | <source lang="bash">Open simple document
| |
- | Open XML document
| |
- | Open TXT document</source>
| |
- |
| |
| == Высокое зацепление (High Cohesion) == | | == Высокое зацепление (High Cohesion) == |
| == Контроллер (Controller) == | | == Контроллер (Controller) == |