C++设计模式系列之二结构型模式
2016-06-24 21:11
399 查看
1.Adapter模式
Adapter.hpp:
#ifndef _ADAPTER_HPP #define _ADAPTER_HPP //第三方库 namespace ThirdPartyNameSpace { class ThirdPartyClass { public: ThirdPartyClass(){} ~ThirdPartyClass(){} void ThirdPartyMethod(){} }; }; //我们内部定义好的接口 struct IMethod { virtual void Method() = 0; }; //内部实现的接口子类 class CustomMethod : public IMethod { public: void Method(){} }; //外部第三方适用我们配器实现接口统一 class ThirdPartyAdapter : public IMethod { public: ThirdPartyAdapter( ThirdPartyNameSpace::ThirdPartyClass *p ) { mp = p; } ~ThirdPartyAdapter() {} void Method() { mp->ThirdPartyMethod(); } private: ThirdPartyNameSpace::ThirdPartyClass *mp; }; #endif
Main.cpp:
#include "Adapter.hpp" ////作用:引用的第三方库方法根现有的接口不一致时,通过中间进行转换将接口保持一致( 记住这种思想即可,其实如何实现你可以自己定义 ) ////缺点:当接口函数很多时,中间层不得不每一个都去实现一次,哪怕非纯虚方法,到时候 ////中间层继承的接口暴露许多无用方法,这样很容易出错,感觉其实adapter是折中的方案 ////既然选择第三方库了,那么项目立项的时候就要考虑进来,合理定义接口,如果是后期加入, ////第三方库一般都是独立的库,和现有接口关系不是太大,即便是有关系,也可以通过其他的方案来解决 ////Adapter模式的特殊性比较强( 个人观点,不要为了设计模式而设计模式 ) // int main() { //内部实现的方案1 IMethod *p = new CustomMethod; p->Method(); //外部第三方库实现的方案2 ThirdPartyNameSpace::ThirdPartyClass *ptp = new ThirdPartyNameSpace::ThirdPartyClass; //给内部适配器 IMethod *p2 = new ThirdPartyAdapter( ptp ); //废了这么大劲只是为了接口一致( 强烈建议自己实现满足自己项目的解决方案,有这种思想即是设计模式,当然如果该例子满足最好 ) p2->Method(); delete p2; delete ptp; delete p; return 0; }
2.Facade模式
Facade.hpp:
#ifndef _FACADE_HPP #define _FACADE_HPP //注意A,B,C,D 系统之间没有直接的关系 class ASystem { public: ASystem(){} ~ASystem(){} void DoSomething(){} }; class BSystem { public: BSystem(){} ~BSystem(){} void DoSomething(){} }; class CSystem { public: CSystem(){} ~CSystem(){} void DoSomething(){} }; class DSystem { public: DSystem(){} ~DSystem(){} void DoSomething(){} }; //测试ab系统模块 class TestAB { public: TestAB() { mpa = new ASystem; mpb = new BSystem; } virtual ~TestAB() { delete mpa; delete mpb; } //外部只关心调用Test方法,A,B系统内部我们不关心,这里只做聚合功能模块 void Test() { mpa->DoSomething(); mpb->DoSomething(); } private: ASystem *mpa; BSystem *mpb; }; //测试cd系统模块 class TestCD { public: TestCD() { mpc = new CSystem; mpd = new DSystem; } virtual ~TestCD() { delete mpc; delete mpd; } void Test() { mpc->DoSomething(); mpd->DoSomething(); } private: CSystem *mpc; DSystem *mpd; }; #endif
Main.cpp:
#include "Facade.hpp" //作用:将我们实现的各类对象系统,抽取出来并且封装聚合在一个类中完成特定的功能 //记住这种思想即可,将各个功能类封装在另一个类中,通过这个聚合类,完成某种高级调用 int main() { //例如测试AB系统,我们将AB封装在TestAB用来测试A和B的调用情况外部只需要调用一个接口即可,不关心A,B的底层实现 //那么TestAB就是A和B的聚合组合,我们称之为Facade模式 TestAB *ptab = new TestAB; //理由同上 TestCD *ptcd = new TestCD; ptab->Test(); ptcd->Test(); delete ptcd; delete ptab; return 0; }
3.Proxy模式
Proxy.hpp:
#ifndef _PROXY_HPP #define _PROXY_HPP #include <string> typedef char c8; typedef const char* cc8p; //网络代理为典型例子( 包括但不限于例子 ) class Proxy { public: Proxy(){} ~Proxy(){} //请求代理 void ProxyLogin( cc8p pUsr, cc8p pPwd, cc8p pProxyIP, int ProxyPort, cc8p pProxyUsr, cc8p pProxyPwd, cc8p pTargetIp, int TargetPort ){} //代理服务器回传数据 void OnProxyRecv( void *p ){} }; class LoginUI { public: LoginUI(){} ~LoginUI(){} void OnClickedLoginBtn() { cc8p pUsr = "test001"; cc8p pPwd = "123456"; strcpy( mUsr, pUsr ); strcpy( mPwd, pPwd ); } c8 mUsr[ 16 ]; c8 mPwd[ 16 ]; }; #endif
Main.cpp:
#include "Proxy.hpp" //作用:特定的功能委托或者转交给其他对象完成,我们称之为proxy代理模式 //例如:(智能指针委托管理对象生命周期,智能锁委托管理锁对象的锁定和解锁,或者其他大部分异步调用的过程) //下面模拟网络上最常用的网络代理 int main() { //登陆用户接口UI LoginUI *pUsrInterface = new LoginUI; //模拟用户点击登陆,得到输入的账号和密码 pUsrInterface->OnClickedLoginBtn(); //OK本地网络太卡了我们通过代理服务器连接游戏登陆服 Proxy *pProxy = new Proxy; pProxy->ProxyLogin( pUsrInterface->mUsr, //用户名数据 pUsrInterface->mPwd, //用户密码 "xxx.xxx.xxx.xxx", //代理服务器地址 8564, //代理服务器端口 "proxyUID", //代理账号 "proxyPwd", //代理密码 "xxx.xxx.xxx.xxx", //目标服务器地址 5876 //目标服务器端口 ); //剩下的就是等待代理服务器返回数据触发pProxy->OnProxyRecv方法 delete pProxy; delete pUsrInterface; return 0; }
4.Flyweight模式
Flyweight.hpp:
#ifndef _FLY_WEIGHT_HPP #define _FLY_WEIGHT_HPP #include <string> #include <vector> typedef std::string xc; class FlyWeight { public: FlyWeight(){} ~FlyWeight(){}; xc mKey; }; class FlyWeightMgr { public: FlyWeightMgr(){}; virtual ~FlyWeightMgr() { for( size_t i = 0; i < mFlyWeights.size(); ++i ) { delete mFlyWeights[i]; } mFlyWeights.clear(); }; FlyWeight* GetFlyWeight( const xc &key ) { for( size_t i = 0; i < mFlyWeights.size(); ++i ) { if( mFlyWeights[i]->mKey == key ) { return mFlyWeights[i]; } } FlyWeight *p = new FlyWeight; p->mKey = key; mFlyWeights.push_back( p ); return p; } private: std::vector< FlyWeight* > mFlyWeights; }; #endif
Main.cpp:
#include "FlayWeight.hpp" //作用:共享实例,已存在就返回,不存在就新建,然后追加到缓冲池中等待被使用 //这种模式,我们应该经常使用,只是不知道叫什么名字而已 //一般这种模式,我们会对对象的创建和销毁内部进行管理 int main() { //典型管理器 FlyWeightMgr *pMgr = new FlyWeightMgr; //获取值为xfx的组件 FlyWeight *p1 = pMgr->GetFlyWeight("xfx"); FlyWeight *p2 = pMgr->GetFlyWeight("xfx"); //这两个值必然相等为true bool b = p1 == p2; delete pMgr; return 0; }
5.Bridge模式
Bridge.hpp:
#ifndef _BRIDGE_HPP #define _BRIDGE_HPP //移动 class Move { public: Move(){} virtual ~Move(){} virtual void move() = 0; }; //地面单位移动 class LandMove : public Move { public: LandMove(){} ~LandMove(){} void move(){} }; //空中单位移动 class AirMove : public Move { public: AirMove(){} ~AirMove(){} void move(){} }; class Unit { public: Unit( Move *p ) { mp = p; } virtual ~Unit(){} virtual void move() { mp->move(); } //...其他方法 protected: Move *mp; //...其他属性 }; //scv 地面单位 class SCV : public Unit { public: SCV( Move *p ) :Unit( p ) {} ~SCV(){} }; //坦克 地面单位 class Tank : public Unit { public: Tank( Move *p ) :Unit( p ) {} virtual ~Tank(){} }; //维京 空中单位 class Viking : public Unit { public: Viking( Move *p ) :Unit( p ) {} ~Viking(){} }; //渡鸦 空中单位 class Raven : public Unit { public: Raven( Move *p ) :Unit( p ) {} ~Raven(){} }; #endif
Main.cpp:
#include "Bridge.hpp" //作用:将本来录属于对象的行为,单独抽象出来成类,通过接口提供 //这样做的好处是,可以降低耦合,当行为发生改变时,原来的对象我们根本不用去管 //例如星际争霸2中的单位例子: int main() { //地面单位移动算法,需要检测碰撞什么的 Move *pLandMove = new LandMove; Unit *pScv = new SCV( pLandMove ); Unit *pTank = new Tank( pLandMove ); //空中单位移动算法,基本不需要检测地图碰撞 Move *pAirMove = new AirMove; Unit *pViking = new Viking( pAirMove ); Unit *pRaven = new Raven( pAirMove ); pScv->move(); pTank->move(); pViking->move(); pRaven->move(); delete pScv; delete pTank; delete pViking; delete pRaven; delete pLandMove; delete pAirMove; return 0; }
6.Decorator模式
Decorator.hpp:
#ifndef _DECORATOR_HPP #define _DECORATOR_HPP #include <stdio.h> class Component { public: Component(){} virtual ~Component(){} virtual void Operate(){} }; //默认的职责,只有文件压缩 class File7z : public Component { public: File7z(){} ~File7z(){} virtual void Operate() { printf( "7z文件压缩中...\n" ); } }; class Algorithm : public Component { public: Algorithm( Component *p ) { mp = p; } virtual ~Algorithm() { delete mp; } protected: //上一个操作对象 Component *mp; }; class AES256 : public Algorithm { public: AES256( Component *p ) :Algorithm( p ) {} ~AES256(){} virtual void Operate() { //上一个职责 mp->Operate(); printf( "aes256加密中..\n" ); } }; class CheckError : public Algorithm { public: CheckError( Component *p ) :Algorithm( p ) {} ~CheckError(){} virtual void Operate() { //上一个职责 mp->Operate(); printf( "检测文件包是否出错中...\n" ); } }; #endif
Main.cpp:
#include "Decorator.hpp" //作用:给一个对象的行为添加新的职责,两两直接可以相互组合成新的职责,而不用在定义新的组合功能类 //例如文件压缩过程 压缩->加密->检测 等等例子可能不是太恰当,记住这种添加职责的思想即可 int main() { //默认只有文件压缩 Component *pFile7z = new File7z; //给pFile7z添加加密 Component *pAes256 = new AES256( pFile7z ); //给pFile7z加密后检测是否出错 Component *pCheck = new CheckError( pAes256 ); //执行 pCheck->Operate(); delete pCheck; //或者直接链式操作 printf( "----\n" ); pCheck = new CheckError( new AES256( new File7z ) ); pCheck->Operate(); delete pCheck; return 0; }
未完待续...
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- PropertyChangeListener简单理解
- 关于指针的一些事情
- 什么是设计模式
- 设计模式之创建型模式 - 特别的变量问题
- 七、设计模式——装饰模式
- 设计模式总结
- 设计模式之创建型模式
- 浅谈设计模式的学习
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Ruby设计模式编程之适配器模式实战攻略
- 实例讲解Ruby使用设计模式中的装饰器模式的方法
- 设计模式中的模板方法模式在Ruby中的应用实例两则
- Ruby设计模式编程中对外观模式的应用实例分析
- 实例解析Ruby设计模式编程中Strategy策略模式的使用
- Ruby中使用设计模式中的简单工厂模式和工厂方法模式
- Ruby使用设计模式中的代理模式与装饰模式的代码实例
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本