[设计模式、C++、go]结构型模式:适配器模式

[设计模式、C++、go]结构型模式:适配器模式,第1张

[设计模式、C++、go]结构型模式:适配器模式

文章目录
  • 适配器模式
    • 介绍
    • 类图
    • 代码实现
      • 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公司的员工员工信息是同一个类处理的(姓名、电话、身份z、职位、公司电话);A公司最近收购B公司,B公司的员工信息是分成两个类处理的,基本信息(姓名,电话,身份z),公司信息(身份z,职位,公司电话) ;公司要求统一处理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 _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 _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 _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(StaffbaseInfo{staff.GetName(), staff.GetPhone(), staff.GetIDCard()})
	s.sc.AddStaffInfo(StaffCompanyInfo{staff.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.Apdater{staffBCompanys, staffBbases}
	tar.GetStaffInfo()
优缺点

优点:

  • 更好的复用性
    适配器模式可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定他们就成
  • 增加了类的透明性
    对高层次模块是透明的,也是它不需要关心的。
  • 提高了类的复用度
    当然了,源角色在原有的系统中还是可以正常使用,而在目标角色中也可以充当新的演员。
  • 灵活性非常好
    某一天,突然不想要适配器,没问题,删除掉这个适配器就可以了,其他的代码都不用修改,基本上就类似一个灵活的构件,想用就用,不想就卸载。

缺点:

  • 过多的使用适配器,会使系统比较凌乱
    明明看到调用的是A接口,其实内部被适配成了B接口来实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
注:

如果能事先预防接口不同的问题,不匹配问题就不会发生;在有小的接口不统一问题发生时,及时重构,问题不至于扩大;只有碰到无法改变原有设计和代码的情况时,才考虑适配。事后控制不如事中控制,事中控制不如事前控制。(《大话设计模式》)

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5692415.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存