Текущая версия |
Ваш текст |
Строка 1: |
Строка 1: |
| = Порождающие паттерны проектирования = | | = Порождающие паттерны проектирования = |
| == Абстрактная фабрика (Abstract Factory, Factory), др. название Инструментарий (Kit) == | | == Абстрактная фабрика (Abstract Factory, Factory), др. название Инструментарий (Kit) == |
- | <source lang="cpp">#include <iostream>
| |
- |
| |
- | class CLanguage
| |
- | {
| |
- | public:
| |
- | virtual void generate() = 0;
| |
- | };
| |
- |
| |
- | class CPytnon : public CLanguage
| |
- | {
| |
- | public:
| |
- | void generate() { std::cout << "Generate python code" << std::endl; }
| |
- | };
| |
- |
| |
- | class CJava : public CLanguage
| |
- | {
| |
- | public:
| |
- | void generate() { std::cout << "Generate java code" << std::endl; }
| |
- | };
| |
- |
| |
- | class CLangFactory
| |
- | {
| |
- | public:
| |
- | virtual CLanguage* createLanguage() = 0;
| |
- | };
| |
- |
| |
- | class CPythonFactory : public CLangFactory
| |
- | {
| |
- | public:
| |
- | CLanguage* createLanguage(){ return new CPytnon(); }
| |
- | };
| |
- |
| |
- | class CJavaFactory : public CLangFactory
| |
- | {
| |
- | public:
| |
- | CLanguage* createLanguage() { return new CJava(); }
| |
- | };
| |
- |
| |
- | class CCodeGenerator
| |
- | {
| |
- | public:
| |
- | CCodeGenerator(CLangFactory* factory)
| |
- | {
| |
- | CLanguage *pLang = factory->createLanguage();
| |
- | pLang->generate();
| |
- | delete pLang;
| |
- | delete factory;
| |
- | }
| |
- | };
| |
- |
| |
- | CLangFactory* createCodeFactory()
| |
- | {
| |
- | int nLang = -1;
| |
- | std::cout << "Enter Language type (0: Python, 1: Java): ";
| |
- | std::cin >> nLang;
| |
- |
| |
- | switch( nLang )
| |
- | {
| |
- | case 0: return new CPythonFactory();
| |
- | case 1: return new CJavaFactory();
| |
- | default: std::cout << "Error choice language..." << std::endl; return 0;
| |
- | }
| |
- | }
| |
- |
| |
- | int main()
| |
- | {
| |
- | CLangFactory *plf = createCodeFactory();
| |
- | if( plf )
| |
- | CCodeGenerator cg( plf );
| |
- |
| |
- | return 0;
| |
- | }</source>
| |
- |
| |
| == Одиночка (Singleton) == | | == Одиночка (Singleton) == |
- | === Статический ===
| |
- | <source lang="cpp">class CSingleton
| |
- | {
| |
- | private:
| |
- | static CSingleton m_singleton;
| |
- |
| |
- | private:
| |
- | CSingleton() {}
| |
- | ~CSingleton() {}
| |
- | CSingleton(const CSingleton &) {}
| |
- | CSingleton & operator=(const CSingleton &) { return *this; }
| |
- |
| |
- | public:
| |
- | static CSingleton *instance() { return &m_singleton; }
| |
- | };
| |
- |
| |
- | CSingleton CSingleton::m_singleton;
| |
- |
| |
- | int main(int , char **)
| |
- | {
| |
- | CSingleton *p = CSingleton::instance();
| |
- | // ...
| |
- | return 0;
| |
- | }</source>
| |
- |
| |
- | === Динамический ===
| |
- | <source lang="cpp">class CSingleton
| |
- | {
| |
- | private:
| |
- | static CSingleton *m_pSingleton;
| |
- | static int m_nCounter;
| |
- |
| |
- | private:
| |
- | CSingleton() {}
| |
- | ~CSingleton() {}
| |
- | CSingleton(const CSingleton &) {}
| |
- | CSingleton & operator=(const CSingleton &) { return *this; }
| |
- |
| |
- | public:
| |
- | static CSingleton *instance()
| |
- | {
| |
- | if( m_nCounter == 0 )
| |
- | {
| |
- | m_pSingleton = new CSingleton();
| |
- | }
| |
- | m_nCounter++;
| |
- | return m_pSingleton;
| |
- | }
| |
- | static CSingleton *freeInstance()
| |
- | {
| |
- | if( m_nCounter > 0 )
| |
- | {
| |
- | m_nCounter--;
| |
- | if( m_nCounter == 0 )
| |
- | {
| |
- | delete m_pSingleton;
| |
- | m_pSingleton = 0;
| |
- | }
| |
- | }
| |
- | }
| |
- | };
| |
- |
| |
- | CSingleton *CSingleton::m_pSingleton = 0;
| |
- | int CSingleton::m_nCounter = 0;
| |
- |
| |
- | int main(int , char **)
| |
- | {
| |
- | CSingleton *p = CSingleton::instance();
| |
- |
| |
- | return 0;
| |
- | }
| |
- | </source>
| |
- |
| |
- | === Шаблонный ===
| |
- | <source lang="cpp">class CClass
| |
- | {
| |
- | public:
| |
- | virtual ~CClass(){ }
| |
- | };
| |
- |
| |
- | template <class T>
| |
- | class CTypedSingleton;
| |
- |
| |
- | template<class T>
| |
- | class CTypedWrapper : public T, private CTypedSingleton<T>
| |
- | {
| |
- | public:
| |
- | void operator delete(void *p)
| |
- | {
| |
- | CTypedSingleton<T>::free();
| |
- | }
| |
- | };
| |
- |
| |
- | template <class T>
| |
- | class CTypedSingleton
| |
- | {
| |
- | static T* m_self;
| |
- | static int m_refcount;
| |
- |
| |
- | protected:
| |
- | CTypedSingleton(){}
| |
- | CTypedSingleton(const CTypedSingleton&){}
| |
- | virtual ~CTypedSingleton(){ m_self = 0; }
| |
- | CTypedSingleton &operator=(const CTypedSingleton&){}
| |
- |
| |
- | public:
| |
- | static T *init()
| |
- | {
| |
- | if(!m_self)
| |
- | m_self = new CTypedWrapper<T>;
| |
- | m_refcount++;
| |
- | return m_self;
| |
- | }
| |
- |
| |
- | static void free()
| |
- | {
| |
- | if( m_refcount > 0)
| |
- | {
| |
- | --m_refcount;
| |
- | if( m_refcount == 0)
| |
- | {
| |
- | delete m_self;
| |
- | m_self = 0;
| |
- | }
| |
- | }
| |
- | }
| |
- | };
| |
- |
| |
- | template <class T>
| |
- | T *CTypedSingleton<T>::m_self = 0;
| |
- |
| |
- | template <class T>
| |
- | int CTypedSingleton<T>::m_refcount = 0;
| |
- |
| |
- | int main(int , char **)
| |
- | {
| |
- | CClass *p = CTypedSingleton<CClass>::init();
| |
- | delete p;
| |
- |
| |
- | return 0;
| |
- | }</source>
| |
- |
| |
- | === Многопоточный (double-checked locking) ===
| |
- | <source lang="cpp">#include <cstdlib>
| |
- | #include <boost/thread/once.hpp>
| |
- |
| |
- | template <class T>
| |
- | class Singleton
| |
- | {
| |
- | public:
| |
- | static T& Instance();
| |
- |
| |
- | private:
| |
- | Singleton() {};
| |
- | Singleton(const Singleton&);
| |
- | Singleton& operator=(const Singleton&);
| |
- | virtual ~Singleton() {};
| |
- |
| |
- | static void Init() { boost::call_once(m_init, &Singleton<T>::InitImpl); }
| |
- | static void InitImpl() { m_me = new T; atexit(&Singleton<T>::FreeInstance); }
| |
- | static void FreeInstance() { boost::call_once(m_done, &Singleton<T>::FreeImpl); };
| |
- | static void FreeImpl() { delete m_me; m_me = NULL; }
| |
- | friend int atexit(void (__cdecl *func)(void));
| |
- |
| |
- | private:
| |
- | static T* volatile m_me;
| |
- | static boost::once_flag m_init, m_done;
| |
- | };
| |
- |
| |
- | template <class T>
| |
- | T* Singleton<T>::m_me = NULL;
| |
- |
| |
- | template <class T>
| |
- | boost::once_flag Singleton<T>::m_init = BOOST_ONCE_INIT;
| |
- |
| |
- | template <class T>
| |
- | boost::once_flag Singleton<T>::m_done = BOOST_ONCE_INIT;
| |
- |
| |
- | template <class T>
| |
- | T& Singleton<T>::Instance()
| |
- | {
| |
- | Init();
| |
- | return (*m_me);
| |
- | }</source>
| |
- |
| |
| == Прототип (Prototype) == | | == Прототип (Prototype) == |
- | <source lang="cpp">#include <iostream>
| |
- |
| |
- | // Прототип
| |
- | class CPrototype
| |
- | {
| |
- | public:
| |
- | virtual CPrototype* clone() const = 0;
| |
- | };
| |
- |
| |
- | // Прототип сайта
| |
- | class CSitePrototype : public CPrototype
| |
- | {
| |
- | private:
| |
- | int m_nPages;
| |
- |
| |
- | public:
| |
- | CSitePrototype(int nPages) : m_nPages( nPages ){}
| |
- | CSitePrototype(const CSitePrototype &r) : m_nPages( r.m_nPages ){}
| |
- | virtual CSitePrototype* clone() const { return new CSitePrototype( *this ); }
| |
- |
| |
- | void setPages(int nPages) { m_nPages = nPages; }
| |
- | int getPages() const { return m_nPages; }
| |
- | void printPages() const { std::cout << "Pages: " << m_nPages << std::endl; }
| |
- | };
| |
- |
| |
- | // Клиентская сторона
| |
- | void clientSide()
| |
- | {
| |
- | CPrototype *pPrototype = new CSitePrototype( 256 );
| |
- | for (int n = 0; n < 10; n++)
| |
- | {
| |
- | CSitePrototype *pSite = static_cast<CSitePrototype*>( pPrototype->clone() );
| |
- | pSite->setPages( pSite->getPages() * n );
| |
- | pSite->printPages();
| |
- | delete pSite;
| |
- | }
| |
- | delete pPrototype;
| |
- | pPrototype = 0;
| |
- | }
| |
- |
| |
- | int main()
| |
- | {
| |
- | clientSide();
| |
- | return 0;
| |
- | }</source>
| |
- |
| |
| == Создатель экземпляров класса (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>
| |
- | #include <iostream>
| |
- |
| |
- | class COs
| |
- | {
| |
- | private:
| |
- | int m_nType;
| |
- | int m_nCore;
| |
- | std::string m_szName;
| |
- |
| |
- | public:
| |
- | void setType( int nType ) { m_nType = nType; }
| |
- | void setCore( int nCore ) { m_nCore = nCore; }
| |
- | void setName( std::string szName ) { m_szName = szName; }
| |
- | void print() { std::cout << "Os type: " << m_nType << " core: " << m_nCore << " name: " << m_szName << std::endl; }
| |
- | };
| |
- |
| |
- | class COsBuilder
| |
- | {
| |
- | protected:
| |
- | COs *m_pOs;
| |
- |
| |
- | public:
| |
- | void createNewOs() { m_pOs = new COs(); }
| |
- | COs *os() { return m_pOs; }
| |
- |
| |
- | virtual void setOsType() = 0;
| |
- | virtual void setOsCore() = 0;
| |
- | virtual void setOsName() = 0;
| |
- | };
| |
- |
| |
- | class CLinuxBuilder : public COsBuilder {
| |
- | public:
| |
- | void setOsType() { m_pOs->setType( 0 ); }
| |
- | void setOsCore() { m_pOs->setCore( 11111 ); }
| |
- | void setOsName() { m_pOs->setName( "Red hat" ); }
| |
- | };
| |
- |
| |
- | class CWindowsBuilder : public COsBuilder
| |
- | {
| |
- | public:
| |
- | void setOsType() { m_pOs->setType( 1 ); }
| |
- | void setOsCore() { m_pOs->setCore( 22222 ); }
| |
- | void setOsName() { m_pOs->setName( "Windows 8" ); }
| |
- | };
| |
- |
| |
- | class CSysAdmin
| |
- | {
| |
- | private:
| |
- | COsBuilder *m_pBuilder;
| |
- |
| |
- | public:
| |
- | CSysAdmin(): m_pBuilder(0){}
| |
- | virtual ~CSysAdmin() { freeBuilder(); }
| |
- |
| |
- | void freeBuilder()
| |
- | {
| |
- | if( m_pBuilder )
| |
- | {
| |
- | delete m_pBuilder;
| |
- | m_pBuilder = 0;
| |
- | }
| |
- | }
| |
- | void setBuilder(COsBuilder* pBuilder)
| |
- | {
| |
- | freeBuilder();
| |
- | m_pBuilder = pBuilder;
| |
- | }
| |
- | void construct()
| |
- | {
| |
- | m_pBuilder->createNewOs();
| |
- | m_pBuilder->setOsType();
| |
- | m_pBuilder->setOsCore();
| |
- | m_pBuilder->setOsName();
| |
- | }
| |
- |
| |
- | void printOs(){ m_pBuilder->os()->print(); }
| |
- | };
| |
- |
| |
- | int main()
| |
- | {
| |
- | CSysAdmin sys;
| |
- |
| |
- | sys.setBuilder(new CLinuxBuilder);
| |
- | sys.construct();
| |
- | sys.printOs();
| |
- |
| |
- | sys.setBuilder(new CWindowsBuilder);
| |
- | sys.construct();
| |
- | sys.printOs();
| |
- | }
| |
- | </source>
| |
- |
| |
| == Фабричный метод (Factory Method) или Виртуальный конструктор (Virtual Constructor) == | | == Фабричный метод (Factory Method) или Виртуальный конструктор (Virtual Constructor) == |
- | <source lang="cpp">
| |
- | #include <iostream>
| |
- |
| |
- | class CDocument
| |
- | {
| |
- | public:
| |
- | virtual void save() = 0;
| |
- | };
| |
- |
| |
- | class CWord: public CDocument
| |
- | {
| |
- | public:
| |
- | void save() { std::cout << "Save word document." << std::endl; }
| |
- | };
| |
- |
| |
- | class CExcel: public CDocument
| |
- | {
| |
- | public:
| |
- | void save() { std::cout << "Save excel document." << std::endl; }
| |
- | };
| |
- |
| |
- | class CApplication
| |
- | {
| |
- | int m_nTypeDocument;
| |
- | public:
| |
- | CApplication( int nTypeDocument ):m_nTypeDocument(nTypeDocument){}
| |
- | void setTypeDocument(int nTypeDocument ){ m_nTypeDocument = nTypeDocument; }
| |
- |
| |
- | void saveFile()
| |
- | {
| |
- | CDocument *pDoc = getTypeDocument();
| |
- | if( pDoc )
| |
- | pDoc->save();
| |
- | }
| |
- |
| |
- | CDocument *getTypeDocument()
| |
- | {
| |
- | switch( m_nTypeDocument )
| |
- | {
| |
- | case 0: return new CWord();
| |
- | case 1: return new CExcel();
| |
- | }
| |
- | return 0;
| |
- | }
| |
- | };
| |
- |
| |
- | int main()
| |
- | {
| |
- | CApplication app( 0 );
| |
- | app.saveFile(); // Word
| |
- | app.setTypeDocument( 1 );
| |
- | app.saveFile(); // Excel
| |
- |
| |
- | return 0;
| |
- | }</source>
| |
| | | |
| = Структурные паттерны проектирования классов/обьектов = | | = Структурные паттерны проектирования классов/обьектов = |
| == Адаптер (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">
| |
- | #include <iostream>
| |
- |
| |
- | class CWindowImp
| |
- | {
| |
- | public:
| |
- | virtual void drawWindow() = 0;
| |
- | };
| |
- |
| |
- | class CLinuxWindow : public CWindowImp
| |
- | {
| |
- | void drawWindow() { std::cout << "Draw linux window" << std::endl; }
| |
- | };
| |
- |
| |
- | class CWinWindow : public CWindowImp
| |
- | {
| |
- | void drawWindow() { std::cout << "Draw Windows window" << std::endl; }
| |
- | };
| |
- |
| |
- | class CMacWindow : public CWindowImp
| |
- | {
| |
- | void drawWindow() { std::cout << "Draw Mac window" << std::endl; }
| |
- | };
| |
- |
| |
- | class CWindowFactory
| |
- | {
| |
- | public:
| |
- | enum TYPES
| |
- | {
| |
- | LINUX = 0,
| |
- | WINDOWS,
| |
- | MAC
| |
- | };
| |
- |
| |
- | // будем считать, что у нас фабрика синглтон и все нормально с освобождением памяти... :)
| |
- | static CWindowImp *getWindowImp( CWindowFactory::TYPES type )
| |
- | {
| |
- | switch( type )
| |
- | {
| |
- | case LINUX: return new CLinuxWindow();
| |
- | break;
| |
- | case WINDOWS: return new CWinWindow();
| |
- | break;
| |
- | case MAC: return new CMacWindow();
| |
- | break;
| |
- | }
| |
- | return 0;
| |
- | }
| |
- |
| |
- | static CWindowImp *makeWindow()
| |
- | {
| |
- | // Будем считать, что мы узнали какая у нас ОС
| |
- | return getWindowImp(CWindowFactory::LINUX);
| |
- | }
| |
- | };
| |
- |
| |
- | class CWindow
| |
- | {
| |
- | public:
| |
- | void draw(){ getWindowImp()->drawWindow(); }
| |
- | CWindowImp *getWindowImp(){ return CWindowFactory::makeWindow(); }
| |
- | };
| |
- |
| |
- | int main()
| |
- | {
| |
- | CWindow win;
| |
- | win.draw();
| |
- | }</source>
| |
- |
| |
| == Низкая связанность (Low Coupling) == | | == Низкая связанность (Low Coupling) == |
| == Приспособленец (Flyweight) == | | == Приспособленец (Flyweight) == |
Строка 784: |
Строка 24: |
| == Команда (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) == |