前阵子,笔者在网上淘来一个二手显示屏来搭配我装好的主机,但是送到手上后我却找不到电源适配器的踪迹。于是我就在家找了根电源线接上了显示屏,倒是能亮,就是屏幕闪得和机关枪似的。这是因为我的显示屏需要12V的供电,我找的这根是5V的……
电源适配器的作用就是把220V的交流电转换成显示器的电压,起到一个转换的作用,我们的适配器模式(Adapter)也是这个意思。
介绍
适配器模式是一种结构型模式,旨在解决不同接口间的不兼容问题。
在一些情况下,我们可能需要一些老的代码接口放在新的环境,这时就可以考虑使用适配器模式了。
适配器模式有以下三个角色:
1、目标接口,即适配器类的统一接口,规范了每一个适配器的行为。也能够允许用户灵活切换适配器。
2、适配者类,其实更像是“被适配者“,就是被适配器转换的主人公,相当于电源适配器转换的220V电源。
3、适配器类,实际发生转换的地方,是目标接口的具体实现,即电源适配器本身。
根据适配者与适配器的关系,适配器又可以被分为类适配器(继承)和对象适配器(组合或委托)。而且,适配器模式一般在开发的初阶段很难用得到,而是会用在已有的代码中解决存在的问题。
类适配器
这里假设我们要调用一个人物移动的方法,他规定了我们上下左右的移动方法。但是我们只需要左右移动就好了,这时就可以使用适配器模式,达到简化参数的作用了,这也是适配器模式使用的一个关键场景。
#include<iostream>
using namespace std;
/*目标接口*/
class Target {
public:
virtual void request(int left, int right) = 0; //目标接口方法
virtual ~Target() = default;
};
/*适配者*/
class Adaptee {
public:
void move(int W, int A, int S, int D) {cout << "按下W后,在y轴给予一个大小为" << W << "的速度" << endl;cout << "按下A后,在x轴给予一个大小为" << -A << "的速度" << endl;cout << "按下S后,在y轴给予一个大小为" << -S << "的速度" << endl;cout << "按下D后,在x轴给予一个大小为" << D << "的速度" << endl;}
};
/*适配器*/
//类适配器模式,使用继承的方式链接适配器与适配者
class Adapter : public Target, public Adaptee {
public:
//只需要用到左与右的速度,所以将上与下的速度设置为0
void request(int left, int right) override {
//调用适配者的方法
move(0, left, 0, right);}
};
可以看到,这里的适配器和适配者是通过继承的关系连接的。但是继承的方法没有灵活性,有着只能单一继承的关系,所以更推荐下面组合的方式连接。
对象适配器
这里再假设我们需要做一个音频适配器,原本的音频是MP3格式的,而我们新环境需要一个OGG格式的音频,这时的适配器起到了转换数据的作用,也是适配器的一个关键场景。
#include<iostream>
using namespace std;
/*目标接口*/
class Target {
public:
virtual void request() = 0; //目标接口方法
virtual ~Target() = default;
};
/*适配者*/
class Adaptee {
public:
void playMusic() {cout << "我播放了一段mp3音频" << endl;}
};
/*适配器*/
//类适配器模式,使用继承的方式链接适配器与适配者
class Adapter : public Target {
public:Adaptee* adaptee;
//只需要用到左与右的速度,所以将上与下的速度设置为0
void request() override {
//调用适配者的方法adaptee->playMusic();}
private:
void convert() {cout << "您输出的音频已经成功转换!" << endl;cout << "我播放了一段ogg音频" << endl;}
};
这样一来,适配器与适配者通过组合的方式连接,更灵活。实际开发中也是类似的框架。
小结
这就是适配器模式的使用方法了,常常用来连结新旧代码或是实现数据转换,总体来说非常简单,不难理解。
如有补充交流欢迎留言,我们下次再见~
参考列表:
菜鸟教程-设计模式:www.runoob.com