[设计模式]结构模式-适配模式(C++描述)

[设计模式]结构模式-适配模式(C++描述)

second60 20180429

1. 什么是适配模式

在现有接口中,不修改原有接口的情况下,增加适配器,支持客户的需求。

适配器分为:类适配器模式和对象适配器模式。

 

现实生活中最简单的例子:手机能电器,我们家用电压为220V(Adaptee),但我们的手机只需12V的电压(Target)来充电。所以中间需要一个电压适配器(Adapter)来转换电压。

 

概念:

接口继承:通过继承子类获得了父类的接口(子类实现父类接口)

实现继承:通过继承子类获得父类的实现(子类调用父类接口)

 

C++

public继承:即是接口继承,也是实现继承(能重载父类的接口,又获得父类的接口实现)。

private继承:父类中的接口都变为private,只能是实现继承。

纯抽象基类:可以模似接口继承。

2. 适配器模式结构图

 

类适配模式

 

对象适配模式

区别:

类适配模式的Adapter采用继承的方式实现Adaptee的接口。

对象模式的Adapter中采用组合的方式实现Adaptee接口。

 

分析:

1. Target为面向用户的接口

2. Adaptee为原有功能接口

3. Adapter为适配器,在原有的接口上适配新功能

 

3 代码实现

3.1对象适配模式

// 目标接口

class  Target

{

public:

virtual ~Target(){}

virtual void Request(){cout << “Target::Request” << endl;}

};

// 原有接口

class  Adaptee

{

public:

Adaptee(){}

~Adaptee(){}

void SpecificRequest(){cout << “ Adaptee::SpecificRequest” << endl;}

};

//适配器

class  Adapter:public  Target

{

public:

Adapter(Adaptee *adaptee){_adaptee = adaptee;}

~Adapter(){}

void Request()

{

// do before....

_adaptee ->SpecificRequest();

// do after...

}

private:

Adaptee * _adaptee;

};

//使用

int main(int argc, char** argv)

{

Adaptee *adaptee = new Adaptee();

Target*  target = new Adapter(adaptee);

target->Request();

return 0;

}

 

3.2 类适配模式

// 目标接口

class  Target

{

public:

virtual ~Target(){}

virtual void Request(){cout << “Target::Request” << endl;}

};

// 原有接口

class  Adaptee

{

public:

Adaptee(){}

~Adaptee(){}

void SpecificRequest(){cout << “ Adaptee::SpecificRequest” << endl;}

};

//适配器, public 为接口继承和实现继承,private为实现继承

class  Adapter:public Target,private Adaptee

{

public:

Adapter(){;}

~Adapter(){}

void Request()

{

// do before....

Adaptee::SpecificRequest();

// do after...

}

};

//使用

int main(int argc, char** argv)

{

Target*  target = new Adapter();

target->Request();

return 0;

}

 

4 适配器的使用场景

适配器模式使用非常广泛,非常常用。

 

在系统开发中,经常遇上这样的问题:在已经开发好了一套接口,或使用第三方接口,但是接口对于现在需求并不适合,需要通过一定的修改在支持,而不想改变原有的逻辑。此时,适配器就派上了用场。

 

使用条件:

1. 原有接口不适用客户需求

2. 客户无须只知内部实现,只知道接口。

 

1:用户需求,某系统保存玩家信息。用户并不关心你使用什么数据库,只需保存玩家信息即可。设计的时候,一开始采用MYSQL 数据库,但后来又采用ORACLE数据库。这就非常适合用适配器,用Target写一套标准API给用户调用即可,对于接口基本实现由Adapter配置实现。

// 统一客户接口

class DBTarget

{

public:

virtual ~DBTarget(){}

virtual int insert(){}

virtual int delete(){}

virtual int update(){}

virtual int select(){}

}

// DBAdaptee抽象类

class DBAdaptee

{

public:

virtual ~DBAdaptee(){}

virtual int insert(){}

virtual int delete(){}

virtual int update(){}

virtual int select(){}

}

class MysqlAdaptee:public DBAdaptee{}// mysql API

class OracleAdaptee:public DBAdaptee{}// oracle ApI

class Db2Adaptee:public DBAdaptee{}//db2 Api

// 统一适配器

class Adaptor:public DBTarget

{

public:

Adaptor(DbAdaptee* adaptee){_adaptee = adaptee;}

int insert(){_adaptee->insert();}

int delete(){_adaptee->delete();}

int update(){_adaptee->update();}

int select(){_adaptee->select();}

private:

DBAdaptee* _adaptee;

};

// 使用

int main(int argc, char** argv)

{

// 配置读取

int db_type = Conf.db_type;

 

//工厂模式生成DBAdaptee

DBAdaptee* dbAdaptee= DBAdapteeFactory::create(dbt_type);

 

DBTarget*  dbTarget= new Adaptor(dbAdaptee);

dbTarget->select();

dbTarget->update();

dbTarget->insert();

dbTarget->delete();

}

 

分析:

1. 上面DB适配器,无需修改任何代码,只需修改配置,即可支持不同数据库

2. 用户无须关心内部接口的实现

3. 如果需要新增数据库(MongoDB,只需添加MongoDBAdaptee,和工厂支持即可。

 

其实,上面的DB例子就是通用的DB适配器,对用户做到DB无关性。

 

5 总结

上面的例子,简单的讲了适配器的例子,想必都清楚适配器的优点了。我就不多说了。设计模式对于面向对象设计是博大精深。

 

  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值