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;
}
未完待续...