设计模式—适配器模式(Adapter)
1.作用
适配器模式是一种补就模式。
目的:将老接口适配成新接口的方法
2.定义
适配器模式(Adapter):将一个类的接口转换成客户希望的另一个接口。
Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
这两种模式中,对象结构模式使用比较广泛,原因是:
- 1.使用组合的设计优于继承, 可以更好的解耦;
- 2.很多语言不支持多重继承,如Java,C#…。
故类结构型适配器模式使用较少,对象结构适配器模式使用更多。
3.模式结构
适配器模式包含如下角色:
-
target:目标抽象类
-
adapter:适配器类
-
adaptee:适配者类
-
client:客户类
适配器模式有对象适配器和类适配器两种实现: -
对象适配器模式结构图:
-
类适配器模式结构图:
4.代码分析
以下代码是对象适配器模式的实现
main.cpp
#include<iostream>
#include"adaptee.hpp"
#include"adapter.hpp"
#include"target.hpp"
using namespace std;
// 适配器设计模式的目的:使用新接口可以调用老方法
/*
适配器模式的主要优点:将目标类和适配者类解耦,增加了类的透明性和复用性,
同时系统的灵活性和扩展性都非常好,更换适配器或者增加新的适配器都
非常方便,符合“开闭原则”。
*/
int main(int argc, const char** argv) {
// 老接口适配
adaptee* ade = new adaptee();
target* tar = new adapter(ade);
tar->request();
// 新接口
tar = new target();
tar->request();
return 0;
}
适配器类:adapter.hpp
#ifndef ADAPTER_HPP
#define ADAPTER_HPP
#include"./adaptee.hpp"
#include"./target.hpp"
// 适配器类(转换):对adaptee的接口与target接口进行适配。
class adapter: public target
{
private:
adaptee* m_adaptee;
public:
adapter(adaptee* ade){
m_adaptee = ade;
};
virtual ~adapter(){
delete m_adaptee;
};
// 适配adaptee之前的老接口
void request(){
m_adaptee->doSpecTarget();
};
};
#endif /* ADAPTER_HPP */
适配者类(老接口):adaptee.hpp
#ifndef ADAPTEE_HPPP
#define ADAPTEE_HPPP
#include<iostream>
using namespace std;
// 已存在的老接口:这个类是需要适配的类
class adaptee
{
private:
/* data */
public:
adaptee(){};
virtual ~adaptee(){};
void doSpecTarget() {
cout << "adaptee::doSpecTarget" << endl;
};
};
#endif /* ADAPTEE_HPPP */
目标接口(新接口):target.hpp
#ifndef TARGET_HPP
#define TARGET_HPP
#include<iostream>
using namespace std;
// 目标接口:定义Client使用的与特定领域相关的接口
class target {
public:
virtual void request(){
cout << "target::request" << endl;
};
};
#endif /* TARGET_HPP */
执行结果:
adaptee::doSpecTarget
target::request
5.具体实例
-
举例:假设你们公司有最近收购了一家公司,两家公司都有各自的人员管理系统,两个系统都可以获取每一个员工的姓名。
你们公司系统中接口是:get_new_name();
被收购公司系统中接口是:get_old_name();
现在领导要求用我们公司的系统也可以查看新收购公司的人员信息。很明显二者接口不一样。此时适配器模式就有用了。 -
此处使用对象类型适配器模式,类图如下
-
代码分析
#include"newsystem.hpp"
#include"oldsystem.hpp"
#include"adaptersystem.hpp"
int main() {
// 老接口的适配,老接口适配成新接口的外衣
oldsystem* old_sys = new oldsystem();
newsystem* new_sys = new adaptersystem(old_sys);
new_sys->get_new_name();
new_sys = new newsystem();
new_sys->get_new_name();
return 0;
}
被收购公司系统中接口:
#ifndef A3A942A1_96D2_4678_A832_56E8C8B5EBEB
#define A3A942A1_96D2_4678_A832_56E8C8B5EBEB
#include <iostream>
class oldsystem
{
public:
oldsystem(){};
virtual ~oldsystem(){};
virtual void get_old_name(){
std::cout << "oldsystem::get_old_name" << std::endl;
};
};
#endif /* A3A942A1_96D2_4678_A832_56E8C8B5EBEB */
自己公司系统中接口:
#ifndef CE425CCB_BED2_43F5_9CD4_B41D6EC75714
#define CE425CCB_BED2_43F5_9CD4_B41D6EC75714
#include <iostream>
class newsystem
{
public:
newsystem(){};
virtual ~newsystem(){};
virtual void get_new_name(){
std::cout << "newsystem::get_new_name" << std::endl;
};
};
#endif /* CE425CCB_BED2_43F5_9CD4_B41D6EC75714 */
适配器类:
#ifndef BE1D74A2_B9E9_4027_ADC2_F3801346C9EA
#define BE1D74A2_B9E9_4027_ADC2_F3801346C9EA
#include"newsystem.hpp"
#include"oldsystem.hpp"
class adaptersystem: public newsystem
{
private:
oldsystem* m_oldsystem; // 需要被适配的接口
public:
adaptersystem(oldsystem* olds){
m_oldsystem= olds;
}
virtual ~adaptersystem(){
delete m_oldsystem;
};
// 统一成新接口
void get_new_name(){
m_oldsystem->get_old_name();
};
};
#endif /* BE1D74A2_B9E9_4027_ADC2_F3801346C9EA */
执行结果:
oldsystem::get_old_name
newsystem::get_new_name
6.go实现具体实例
- 6.1 自己的系统:newsystem.go
package adapter
import "fmt"
// ======================================
// 新系统接口
type INewSystem interface {
GetNewName()
}
// ======================================
type NewSystem struct{}
func NewNewSystem() *NewSystem {
return &NewSystem{}
}
func (ns *NewSystem) GetNewName() {
fmt.Println("NewSystem::GetNewName")
}
- 6.2 收购的系统:oldsystem.go
package adapter
import "fmt"
// ======================================
// 老系统接口
type IOldSystem interface {
GetOldName()
}
// ======================================
type OldSystem struct{}
func NewOldSystem() *OldSystem{
return &OldSystem{}
}
func (ns *OldSystem) GetOldName() {
fmt.Println("OldSystem::GetOldName")
}
- 6.3 适配器类:adapter.go
package adapter
// 适配器类
type Adapter struct{
OldSys IOldSystem // 老系统接口 适配老系统成新系统接口方法
}
func NewAdapter(oldsys IOldSystem) *Adapter {
return &Adapter{ OldSys: oldsys}
}
func (a *Adapter) GetNewName() {
a.OldSys.GetOldName()
}
- 6.4 main.go
package main
import (
"./adapter"
)
func test_adapter() {
old_sys := adapter.NewOldSystem()
ada := adapter.NewAdapter(old_sys)
ada.GetNewName()
new_sys := adapter.NewNewSystem()
new_sys.GetNewName()
}
func main() {
test_adapter()
}
- 6.5 执行结果:
OldSystem::GetOldName
NewSystem::GetNewName