1、 适配器模式是什么?
Adapter:将一个类接口为转化作为客户希望的另一个接口。
使得原本而由于接口不兼容而不能一起工作的那些类可以一起工作。
2、 为何要使用适配器模式?
在软件开发中,系统的数据和行为都正确,但接口不符时,我们需要考虑适配器,目的:是控制范围之外的一个原有对象与某个接口匹配。
主要应用在希望服用一些现存的类,但是接口又与复用环境要求不一致的情况。
如:在早期对代码笃用一些功能等应用上很有实际价值。
3、 如何使用适配器模式?
step1:适配器将待匹配对象作为它的私有成员,
step2:在适配器的构造函数中对待适配对象进行初始化,析构函数中析构待适配对象;
step3:在公共的目标接口中,调用待匹配对象对应接口函数,实现点对点适配。
简单的UML图:
4、 怎样才能用好适配器模式?
(1)在双方都不太容易修改时在使用适配器模式适配
(2)使用第三方软件开发组件,该组件的接口与我们自己系统接口不一致
(3)使用适配器的原则小结:
- 如果能事先预防接口不同的问题,接口不匹配就不会发生;
- 在有小的接口不统一问题发生时,即使重构,问题不至于扩大;
- 只有碰到无法改变原有设计合代码的情况下,才考虑适配。
- 事后控制不如始终事中控制,事中控制不如事前控制。
5、实例-篮球翻译适配器
(1)UML类图
(2)核心实现思路
step1:适配器(翻译员)将待匹配对象(外籍球员)作为它的私有成员,
step2:在适配器(翻译员)的构造函数中对待适配对象(外籍球员)进行初始化(分配内存空间+球员名字),析构函数中析构待适配对象(外籍球员);
step3:在公共的目标接口Attack,Defense中,调用待匹配对象(外籍球员)对应能明白的"进攻"、"防守"函数,实现点对点适配。
(3)主要代码如下:
1.1、IPlayer.h
#pragma once
#include <string>
using namespace std;
class IPlayer
{
public:
IPlayer();
IPlayer(const string& _name);
~IPlayer();
public:
virtual void Attack();//接口:进攻
virtual void Defense();//防守
protected:
string name;
};
1.2 IPlayer.cpp
#include "IPlayer.h"
#include <iostream>
IPlayer::IPlayer()
{
}
IPlayer::IPlayer(const string& _name)
:name(_name)
{
}
IPlayer::~IPlayer()
{
}
void IPlayer::Attack()
{
cout << "进攻" << endl;
}
void IPlayer::Defense()
{
cout << "防守" << endl;
}
2.1 ITranslater.h
#pragma once
#include "IPlayer.h"
#include "ForeignCenter.h"
class ITranslater :
public IPlayer
{
public:
ITranslater();
ITranslater(const string& _name);
~ITranslater();
virtual void Attack() override;//公共接口
virtual void Defense() override;
private:
ForeignCenter* m_pForeignCenter;
};
2.2 ITranslater.cpp
#include "ITranslater.h"
ITranslater::ITranslater()
{
}
ITranslater::ITranslater(const string& _name)
:IPlayer(_name)
{
m_pForeignCenter = new ForeignCenter();
m_pForeignCenter->setName(_name);
}
ITranslater::~ITranslater()
{
delete m_pForeignCenter;
m_pForeignCenter = nullptr;
}
void ITranslater::Attack()
{
m_pForeignCenter->进攻();
}
void ITranslater::Defense()
{
m_pForeignCenter->防守();
}
3.1 ForeignCenter.h
#pragma once
#include <string>
using namespace std;
class ForeignCenter
{
public:
ForeignCenter();
~ForeignCenter();
public:
void 进攻();
void 防守();
public:
string getName();
void setName(const string& _name);
private:
string name;
};
3.2 ForeignCenter.cpp
#include "ForeignCenter.h"
#include <iostream>
ForeignCenter::ForeignCenter()
{
}
ForeignCenter::~ForeignCenter()
{
}
void ForeignCenter::进攻()
{
cout << "外籍中锋-" << name << ",进攻" << endl;
}
void ForeignCenter::防守()
{
cout << "外籍中锋-" << name << ",防守" << endl;
}
std::string ForeignCenter::getName()
{
return name;
}
void ForeignCenter::setName(const string& _name)
{
name = _name;
}
4、main.cpp
#include "IPlayer.h"
#include "Forwards.h"
#include "Center.h"
#include "Guards.h"
#include "ITranslater.h"
#include <iostream>
void test2()
{
cout << "=============test2()=============" << endl;
IPlayer* pPlayer = new Forwards("巴蒂尔");
pPlayer->Attack();
IPlayer* pPlayer1 = new Guards("麦克格雷迪");
pPlayer1->Attack();
IPlayer* pPlayer2 = new ITranslater("姚明");//这个ITranslater翻译家就是姚明(外籍球员)的适配器。可以很好地适配到英语环境中去~~
pPlayer2->Attack();
pPlayer2->Defense();
}
int main()
{
test2();
system("pause");
return 0;
}
此为《大话设计模式》学习心得系列 P171~~