Chapter13:适配器模式
适配器模式(Adapter):
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。简单地说,就是需要的东西就在面前,但却不能使用,而短时间又无法改造它,于是就想办法适配它。适配这个词可以这样理解。比如,有些国家用110V电压,而我们国家用的是220V,但我们的电器,比如笔记本电脑是不能什么电压都能用的,但国家不同,电压可能不相同也是事实,于是就用一个电源适配器,只要是电,不管多少伏,都能把电源变成需要的电压,这就是电源适配器的作用。适配器的意思就是使得一个东西适合另一个东西的东西。
在软件开发中,系统的数据和行为都正确,但接口不符合,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。
何时使用适配器模式:
使用一个已存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就应该考虑用适配器模式。也就是两个类所做的事情相同或相似,但是具有不同的接口时要使用它。而且由于类都共享同一个接口,使得客户端代码可以统一调用同一接口。这样应该可以更简单、更直接、更紧凑。
适配器模式要在双方都不太容易修改的时候再使用适配器模式适配。
赏图:
实际应用
工程结构
(1)球员类(Target) Player.h
(2)外籍球员类(Adaptee) ForeignCenter.h
(3)翻译类(Adapter) Translator.h
(4)客户端类(Client) AdapterApp.cpp
(1)球员类(Target) Player.h
#ifndef _PLAYER_H_
#define _PLAYER_H_
#include <string>
#include <iostream>
using namespace std;
class Player
{
public:
Player(const string& strName)
{
m_strName = strName;
}
virtual void Attack(void) = 0; // 进攻
virtual void Defense(void) = 0; // 防守
protected:
string m_strName;
};
// 前锋类
class Forwards : public Player
{
public:
Forwards(const string& strName)
: Player(strName)
, m_strName(strName){}
void Attack(void)
{
cout << "Forward:" <<m_strName << " attack" << endl;
}
void Defense(void)
{
cout << "Forward:" <<m_strName << " defense" << endl;
}
private:
string m_strName;
};
// 中锋类
class Center : public Player
{
public:
Center(const string& strName)
: Player(strName)
, m_strName(strName){}
void Attack(void)
{
cout << "Center:" <<m_strName << " attack" << endl;
}
void Defense(void)
{
cout << "Center:" <<m_strName << " defense" << endl;
}
private:
string m_strName;
};
// 后卫类
class Guards : public Player
{
public:
Guards(const string& strName)
: Player(strName)
, m_strName(strName){}
void Attack(void)
{
cout << "Guard:" <<m_strName << " attack" << endl;
}
void Defense(void)
{
cout << "Guard:" <<m_strName << " defense" << endl;
}
private:
string m_strName;
};
#endif// _PLAYER_H_
(2)外籍球员类(Adaptee) ForeignCenter.h
#ifndef _FOREIGN_CENTER_H_
#define _FOREIGN_CENTER_H_
#include <string>
#include <iostream>
using namespace std;
class ForeignCenter
{
public:
void SetName(const string& strName){ m_strName = strName; }
string GetName(void){ return m_strName; }
// 外籍中锋只懂中文进攻
void ForeignAttack()
{
cout << "外籍中锋:" <<m_strName << "进攻" << endl;
}
// 外籍中锋只懂中文防守
void ForeignDefense()
{
cout << "外籍中锋:" <<m_strName << "防守" << endl;
}
private:
string m_strName;
};
#endif// _FOREIGN_CENTER_H_
(3)翻译类(Adapter) Translator.h
#ifndef _TRANSLATOR_H_
#define _TRANSLATOR_H_
#include "Player.h"
#include "ForeignCenter.h"
class Translator : public Player
{
public:
// 声明并实例化一个内部“外籍中锋”对象,表明翻译者与外籍球员有关联
Translator(const string& strName)
: Player(strName)
, m_pForeignCenter(NULL)
{
m_pForeignCenter = new ForeignCenter();
m_strName = strName;
}
~Translator()
{
if (NULL != m_pForeignCenter)
{
delete m_pForeignCenter;
m_pForeignCenter = NULL;
}
}
// 翻译者将“attack”翻译成“进攻”告诉外籍中锋
void Attack(void)
{
if (NULL != m_pForeignCenter)
{
m_pForeignCenter->ForeignAttack();
}
}
// 翻译者将“Defense”翻译成“防守”告诉外籍中锋
void Defense(void)
{
if (NULL != m_pForeignCenter)
{
m_pForeignCenter->ForeignDefense();
}
}
private:
ForeignCenter* m_pForeignCenter;
string m_strName;
};
#endif// _TRANSLATOR_H_
(4)客户端类(Client) AdapterApp.cpp
// AdapterApp.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "Player.h"
#include "Translator.h"
#define FREE_PTR(Pointer) \
{ \
if (NULL != Pointer)\
{ \
delete Pointer; \
Pointer = NULL; \
} \
}
int _tmain(int argc, _TCHAR* argv[])
{
Player* pCarter = new Forwards("carter");
if (NULL != pCarter)
{
pCarter->Attack();
}
Player* pKobe = new Guards("Kobe");
if (NULL != pKobe)
{
pKobe->Attack();
}
// 翻译者告诉yao,教练要求你进攻和防守
Player* pYao = new Translator("Yao");
if (NULL != pYao)
{
pYao->Attack();
pYao->Defense();
}
Player* pOneal = new Center("o'neal");
if (NULL != pOneal)
{
pOneal->Attack();
}
system("pause");
FREE_PTR(pOneal);
FREE_PTR(pYao);
FREE_PTR(pKobe);
FREE_PTR(pCarter);
return 0;
}