您的位置:首页 > 编程语言 > C语言/C++

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++ 设计模式 结构型