[设计模式C++go]结构型模式:适配器模式
Posted 凌星An
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[设计模式C++go]结构型模式:适配器模式相关的知识,希望对你有一定的参考价值。
适配器模式
介绍
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。
这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。
其定义:
Convert the interface of a class into another interface clients
expect.Adapter lets classes work together that couldn't otherwise because ofincompatible interfaces.(将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。)
比如:你现在遇到一个外国人,但是你不懂外语,那么怎么交流呢?可以使用手机即时翻译软件,让你们能顺利沟通,这就体现了适配器模式的原理。
意图: 将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
主要解决: 在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。
何时使用:
1、系统需要使用现有的类,而此类的接口不符合系统的需要。
2、想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。
3、通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口。)
如何解决: 继承或依赖(推荐)。
关键代码: 适配器继承或依赖已有的对象,实现想要的目标接口。
类图
代码实现
我们现在处于A公司,A公司的员工员工信息是同一个类处理的(姓名、电话、身份证、职位、公司电话);A公司最近收购B公司,B公司的员工信息是分成两个类处理的,基本信息(姓名,电话,身份证),公司信息(身份证,职位,公司电话) ;公司要求统一处理A,B公司员工信息。 用代码实现此过程
C++
/A公司员工信息处理///
class staffInfo
public:
staffInfo(std::string name="", std::string phone="", std::string idCard="", std::string jobPosition="", std::string OfficePhone="")
_name = name;
_phone = phone;
_idCard = idCard;
_jobPosition = jobPosition;
_OfficePhone = OfficePhone;
void GetStaffInfo()
std::cout << "name:" << _name << std::endl;
std::cout << "phone:" << _phone << std::endl;
std::cout << "idCard:" << _idCard << std::endl;
std::cout << "jobPosition:" << _jobPosition << std::endl;
std::cout << "OfficePhone:" << _OfficePhone << std::endl;
std::string GetName()
return _name;
std::string GetPhone()
return _phone;
std::string GetIDCard()
return _idCard;
std::string GetJobPosition()
return _jobPosition;
std::string GetOfficePhone()
return _OfficePhone;
private:
//基本信息
std::string _name;
std::string _phone;
std::string _idCard;
//公司信息
std::string _jobPosition;
std::string _OfficePhone;
;
class Target
public:
virtual void GetStaffInfo() = 0;
virtual void AddStaffInfo(staffInfo staff) = 0;
;
class StaffInfos:public Target
public:
void AddStaffInfo(staffInfo staff)
_map[staff.GetIDCard()] = staff;
void GetStaffInfo()
auto e = _map.begin();
while (e != _map.end())
e->second.GetStaffInfo();
e++;
private:
std::unordered_map<std::string, staffInfo> _map;
;
B公司员工信息//
namespace B
class staffBaseInfo
public:
staffBaseInfo(std::string name="", std::string phone="", std::string idCard="")
_name = name;
_phone = phone;
_idCard = idCard;
void GetStaffInfo()
std::cout << "name:" << _name << std::endl;
std::cout << "phone:" << _phone << std::endl;
std::cout << "idCard:" << _idCard << std::endl;
std::string GetIDCard()
return _idCard;
private:
//基本信息
std::string _name;
std::string _phone;
std::string _idCard;
;
class staffCompanyInfo
public:
staffCompanyInfo(std::string idCard="", std::string jobPosition="", std::string OfficePhone="")
_idCard = idCard;
_jobPosition = jobPosition;
_OfficePhone = OfficePhone;
std::string GetIDCard()
return _idCard;
void GetStaffInfo()
std::cout << "jobPosition:" << _jobPosition << std::endl;
std::cout << "OfficePhone:" << _OfficePhone << std::endl;
private:
std::string _idCard;
//公司信息
std::string _jobPosition;
std::string _OfficePhone;
;
class StaffBaseInfos
public:
void AddStaffInfo(staffBaseInfo staff)
_map[staff.GetIDCard()] = staff;
void GetStaffInfo()
auto e = _map.begin();
while (e != _map.end())
e->second.GetStaffInfo();
e++;
private:
std::unordered_map<std::string, staffBaseInfo> _map;
;
class StaffCompanyInfos
public:
void AddStaffInfo(staffCompanyInfo staff)
_map[staff.GetIDCard()] = staff;
void GetStaffInfo()
auto e = _map.begin();
while(e != _map.end())
e->second.GetStaffInfo();
e++;
private:
std::unordered_map<std::string, staffCompanyInfo> _map;
;
适配类///
class Apdater :public Target
public:
Apdater(B::StaffBaseInfos SBI, B::StaffCompanyInfos SCI)
_SBI = SBI;
_SCI = SCI;
void AddStaffInfo(staffInfo staff)
B::staffBaseInfo tmpBase(staff.GetName(), staff.GetPhone(), staff.GetIDCard());
B::staffCompanyInfo tmpCompany(staff.GetIDCard(), staff.GetJobPosition(), staff.GetOfficePhone());
_SBI.AddStaffInfo(tmpBase);
_SCI.AddStaffInfo(tmpCompany);
void GetStaffInfo()
_SBI.GetStaffInfo();
_SCI.GetStaffInfo();
private:
B::StaffBaseInfos _SBI;
B::StaffCompanyInfos _SCI;
;
测试
A公司处理/
staffInfo Astaff1("小明", "123", "1", "A_enginer", "000");
StaffInfos ASS;
ASS.AddStaffInfo(Astaff1);
B公司处理///
B::staffBaseInfo BstaffB1("小红","124", "2");
B::staffCompanyInfo BstaffC1("2", "B_enginer", "009");
B::StaffBaseInfos SBIS;
SBIS.AddStaffInfo(BstaffB1);
B::StaffCompanyInfos BSCS;
BSCS.AddStaffInfo(BstaffC1);
//
//我们仅需要改变这一处代码就ok了
//Target* t =&ASS;
Target* t = new Apdater(SBIS, BSCS);
t->GetStaffInfo();
go
package Adpater
import "fmt"
/A公司/
type StaffInfo struct
//基本信息
_name string
_phone string
_idCard string
//公司信息
_jobPosition string
_officePhone string
func (s *StaffInfo) SetStaffInfo(name, phone, idCard, jobPosition, officePhone string)
s._name, s._phone, s._idCard, s._jobPosition, s._officePhone = name, phone, idCard, jobPosition, officePhone
func (s *StaffInfo) GetStaffInfo()
fmt.Println("name:", s._name)
fmt.Println("phone:", s._phone)
fmt.Println("IDCard", s._idCard)
fmt.Println("JobPosition", s._jobPosition)
fmt.Println("OfficePhone", s._officePhone)
func (s *StaffInfo) GetName() string
return s._name
func (s *StaffInfo) GetPhone() string
return s._phone
func (s *StaffInfo) GetIDCard() string
return s._idCard
func (s *StaffInfo) GetJobPosition() string
return s._jobPosition
func (s *StaffInfo) GetOfficePhone() string
return s._officePhone
type Target interface
GetStaffInfo()
AddStaffInfo(staff StaffInfo)
type StaffInfos struct
smap map[string]StaffInfo
func (s *StaffInfos) GetStaffInfo()
for _, v := range s.smap
v.GetStaffInfo()
func (s *StaffInfos) AddStaffInfo(staff StaffInfo)
if s.smap == nil
s.smap = make(map[string]StaffInfo)
s.smap[staff.GetName()] = staff
///B公司///
type StaffBaseInfo struct
_name string
_phone string
_idCard string
func (s *StaffBaseInfo) GetStaffInfo()
fmt.Println("name:", s._name)
fmt.Println("phone:", s._phone)
fmt.Println("IDCard", s._idCard)
func (s *StaffBaseInfo) GetIDcard() string
return s._idCard
func (s *StaffBaseInfo) SetStaffInfo(name, phone, idCard string)
s._name, s._phone, s._idCard = name, phone, idCard
type StaffCompanyInfo struct
_idCard string
_jobPosition string
_officePhone string
func (s *StaffCompanyInfo) SetStaffInfo(idCard, jobPosition, officePhone string)
s._idCard, s._jobPosition, s._officePhone = idCard, jobPosition, officePhone
func (s *StaffCompanyInfo) GetStaffInfo()
fmt.Println("JobPosition", s._jobPosition)
fmt.Println("OfficePhone", s._officePhone)
func (s *StaffCompanyInfo) GetIDcard() string
return s._idCard
type StaffBaseInfos struct
smap map[string]StaffBaseInfo
func (s *StaffBaseInfos) AddStaffInfo(staff StaffBaseInfo)
if s.smap == nil
s.smap = make(map[string]StaffBaseInfo)
s.smap[staff.GetIDcard()] = staff
func (s *StaffBaseInfos) GetStaffInfo()
for _, v := range s.smap
v.GetStaffInfo()
type StaffCompanyInfos struct
smap map[string]StaffCompanyInfo
func (s *StaffCompanyInfos) AddStaffInfo(staff StaffCompanyInfo)
if s.smap == nil
s.smap = make(map[string]StaffCompanyInfo)
s.smap[staff.GetIDcard()] = staff
func (s *StaffCompanyInfos) GetStaffInfo()
for _, v := range s.smap
v.GetStaffInfo()
/
//Apdater类///
type Apdater struct
sc StaffCompanyInfos
sb StaffBaseInfos
func (s *Apdater) AddStaffInfo(staff StaffInfo)
s.sb.AddStaffInfo(StaffBaseInfostaff.GetName(), staff.GetPhone(), staff.GetIDCard())
s.sc.AddStaffInfo(StaffCompanyInfostaff.GetIDCard(), staff.GetJobPosition(), staff.GetOfficePhone())
func (s *Apdater) GetStaffInfo()
s.sb.GetStaffInfo()
s.sc.GetStaffInfo()
测试
//A公司
staffA := Adpater.StaffInfo
staffA.SetStaffInfo("小明", "123", "1", "A_enginer", "000")
staffAs := Adpater.StaffInfos
staffAs.AddStaffInfo(staffA)
///B/
staffBbase := Adpater.StaffBaseInfo
staffBbase.SetStaffInfo("小红", "124", "2")
staffBbases := Adpater.StaffBaseInfos
staffBbases.AddStaffInfo(staffBbase)
staffBCompany := Adpater.StaffCompanyInfo
staffBCompany.SetStaffInfo("2", "B_enginer", "009")
staffBCompanys := Adpater.StaffCompanyInfos
staffBCompanys.AddStaffInfo(staffBCompany)
/使用
//var tar Adpater.Target = &staffAs
var tar Adpater.Target = &Adpater.ApdaterstaffBCompanys, staffBbases
tar.GetStaffInfo()
优缺点
优点:
- 更好的复用性
适配器模式可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定他们就成 - 增加了类的透明性
对高层次模块是透明的,也是它不需要关心的。 - 提高了类的复用度
当然了,源角色在原有的系统中还是可以正常使用,而在目标角色中也可以充当新的演员。 - 灵活性非常好
某一天,突然不想要适配器,没问题,删除掉这个适配器就可以了,其他的代码都不用修改,基本上就类似一个灵活的构件,想用就用,不想就卸载。
缺点:
- 过多的使用适配器,会使系统比较凌乱
明明看到调用的是A接口,其实内部被适配成了B接口来实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
注:
如果能事先预防接口不同的问题,不匹配问题就不会发生;在有小的接口不统一问题发生时,及时重构,问题不至于扩大;只有碰到无法改变原有设计和代码的情况时,才考虑适配。事后控制不如事中控制,事中控制不如事前控制。(《大话设计模式》)
以上是关于[设计模式C++go]结构型模式:适配器模式的主要内容,如果未能解决你的问题,请参考以下文章