文章目录

  • 1.概述
  • 2.适配器模式的简单应用
  • 3.适配器模式应用场景与优缺点
  • 4.类适配器
  • 5.小结
  • 参考文献

1.概述

使用设计模式可以提高代码的可复用性、可扩充性和可维护性。适配器模式(Adapter Pattern)属结构性模式,将一个类的接口转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。

何谓适配器模式?适配器模式就是将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。

在适配器模式中,我们可以定义一个包装类,包装不兼容的函数接口和提供该函数接口的对象,这个包装类就是适配器,它所包装的对象就是适配者。

适配器提供给客户需要的函数接口,适配器的实现就是将客户的请求转换成对适配者相应函数接口的引用。也就是说,当客户调用适配器的方法时,适配器方法内部将调用适配者的方法,客户并不是直接访问适配者,而是通过调用适配器方法访问适配者。因为适配器可以使互不兼容的类能够“合作愉快”。

适配器模式的类图:

Client:客户类。
Target:目标抽象类;
Adapter:适配器类;
Adaptee:适配者类;

2.适配器模式的简单应用

下面使用《Head First 设计模式》中用火鸡冒充鸭子的例子来讲解。

假如,我们拥有一个抽象的鸭子类,鸭子会飞,也会叫。绿头鸭实现鸭子的抽象类。

// 抽象鸭类
class Duck {public:virtual void quack() = 0;virtual void fly() = 0;
};// 绿头鸭
class MallardDuck {public:virtual void quack() {cout << "绿头鸭呱呱叫"<< endl;}virtual void fly() {cout << "绿头鸭开始飞"<< endl;}
};

同时,我们拥有火鸡类,火鸡同样可以叫和飞,但是叫声是咯咯叫,飞行也没有鸭子飞的远。

class Turkey {public:void gobble() {cout << "火鸡咯咯叫" << endl;}void fly() {cout << "火鸡短距离飞" << endl;}
};

现在,假设缺少鸭子对象,使用一些火鸡来冒充。因为火鸡的函数接口不同,所以我们不能直接拿来用。那么,可以使用适配器可以来包装火鸡对象和函数接口。

class TurkeyAdapter:public Duck {Turkey turkey;
public:TurkeyAdapter(const Turkey& turkey):turkey(turkey){}virtual void quack() {turkey.gobble();}//火鸡飞行5次才能达到鸭子的飞行距离virtual void fly() {for(int i=0;i<5;++i)turkey.fly();}
};

下面是客户端代码使用火鸡适配器。

#include <iostream>
using namespace std;int main() {MallardDuck mallardDuck;//绿头鸭开始叫和飞mallardDuck.quack();mallardDuck.fly();//火鸡充当鸭子开始叫和飞TurkeyAdapter* fakeDuck=new TurkeyAdapter( Turkey() );fakeDuck->quack();fakeDuck->fly();
}

程序输出结果:

绿头鸭呱呱叫
绿头鸭开始飞
火鸡咯咯叫
火鸡短距离飞
火鸡短距离飞
火鸡短距离飞
火鸡短距离飞
火鸡短距离飞

3.适配器模式应用场景与优缺点

应用场景:
(1)系统需要使用现有的类,而这些类的接口不符合系统的需要。
(2)想要建立一个可以重复使用的类(适配器),用于与一些彼此之间没有太大关联的类建立联系。

优点:
(1)**松散耦合。**将客户端代码和适配者类解耦,通过使用适配器让不兼容的接口变得兼容。
(2)**隐藏和复用。**增加了适配者类(如火鸡类)的复用性,将适配者类的实现封装在适配器中,隐藏了适配者类的具体实现,而且提高了适配者的复用性。
(3)**良好的灵活性和扩展性。**在不修改原有代码的基础上可以增加新的适配器类,符合“开放关闭原则”。

缺点:
采用组合的方式将适配者封装在适配器类中,不能够重写(覆盖)适配者的行为。

4.类适配器

适配器模式分为对象适配器和类适配器。前面所概述的是对象适配器。类适配器使用有限,因为类适配器需要使用多重继承,这个在java、C#中没有办法实现,但在C++中可以实现。

类适配器的类图如下:

类适配器优点:
适配器类继承适配者类,在必要的时候,可以重写适配者的行为。

类适配器缺点:
对于Java、C#等不支持多重继承的语言,一次最多只能适配一个目标类。其使用存在一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。

5.小结

(1)当我们需要使用一个现有的类,但是它的函数接口并不符合我们的需求时,我们可以使用适配器模式。
(2)适配器模式分为类适配器和对象适配器,其中类适配器需要用到多重继承。
(3)适配器模式(对象适配器)将一个对象包装起来改变其函数接口,来适应现有系统的需要;装饰者模式讲一个对象包装起来以增加新的行为和责任;而外观模式将一群对象包装起来,以简化其函数接口。


参考文献

[1] 设计模式读书笔记-----适配器模式
[2] Head First 设计模式(中文版).P235-270

结构型设计模式 (1)—— 适配器模式(Adapter Pattern)相关推荐

  1. 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern)

    [索引页] [源码下载] 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern) 作者:webabcd 介绍 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本 ...

  2. 【设计模式】适配器模式 Adapter Pattern

    适配器模式在软件开发界使用及其广泛,在工业界,现实中也是屡见不鲜.比如手机充电器,笔记本充电器,广播接收器,电视接收器等等.都是适配器. 适配器主要作用是让本来不兼容的两个事物兼容和谐的一起工作.比如 ...

  3. 白话设计模式--结构型模式之 适配器模式(Adapter)

    适配其实在生活中的例子很多.一个变压器就是最好的例子. 我们不能要求供电局为了我们的随身听而把电压变成12V,只能使用一个变压器把220V的电转换成12V的.这就是个适配器的很好的 例子.新的需求就是 ...

  4. 二十三种设计模式[6] - 适配器模式(Adapter Pattern)

    前言 适配器,属于类结构型模式.<设计模式 - 可复用的面向对象软件>一书中将之描述为" 将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可 ...

  5. 结构型设计模式 -- 适配器模式

    一.小案例分析 1.功能需求: 以电源适配器为例. 一个人去外国旅游,住在外国某宾馆,恰好手机没电(手机是双孔插头),但外国宾馆只有三孔插座,宾馆一般不可能为了旅客,将三孔插座换成双孔插座,此时适配器 ...

  6. 设计模式GOF23之-------------------结构型模式(适配器模式、代理模式、桥接模式、装饰模式、组合模式、外观模式、享元模式)

    一 结构型模式 二 适配器模式 下面我将用代码模拟键盘usb接口和ps/2的转接器 的适配器过程: 首先定义客户需求: package GOF23;public interface Target {v ...

  7. 设计模式之结构型模式:适配器模式、桥接模式、组合模式、装饰器模式、代理模式、

    文章目录 什么是结构型模式 适配模式 适配器的数据结构 适配器的实现 缺省适配器 适配器优缺点 适配器模式的使用环境 桥接模式 桥接模式数据结构 桥接模式的实现 桥接模式和适配器模式的联用 桥接模式的 ...

  8. JavaScript设计模式(三):结构型设计模式-外观模式、适配器模式、代理模式、装饰者模式、桥接模式、组合模式、享元模式

    JavaScript设计模式 - 结构型设计模式 套餐服务-外观模式 外观模式(Facade) 水管弯弯-适配器模式 适配器模式(Adapter) 适配异类框架 参数适配 牛郎织女-代理模式 代理模式 ...

  9. 设计模式(结构型)之代理模式(Proxy Pattern)

    PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbob ...

  10. 技术图文:03 结构型设计模式(上)

    结构型设计模式(上) 本教程主要介绍一系列用于如何将现有类或对象组合在一起形成更加强大结构的经验总结. 知识结构: 享元模式 – 实现对象的复用 Sunny 软件公司欲开发一个围棋软件,其界面效果如下 ...

最新文章

  1. Node.js + Express + Springboot实现前后端分离架构
  2. 联想平板电脑win10如何取消触摸键盘按键声音
  3. 淘商们用数据精细化分析客户群体
  4. (译文)JavaScript基础——JavaScript中的深拷贝
  5. java holder 遍历_复合组件editableValueHolder与Bean验证不一致
  6. iPhone Development Blog系列: 如何制作服务条例窗口
  7. 递归优化的这三种方式你知道吗?
  8. idea远程调试修改代码_IDEA远程调试(Remote Debug)Java代码指南
  9. C# 实现 Hyper-V 虚拟机 管理
  10. 卡在linuxctrld进系统_电脑系统出现问题怎么办?学会这七招,电脑系统问题不求人!...
  11. 【转】Android Fragment中使用SurfaceView切换时闪一下黑屏的解决办法
  12. C/c++ http请求
  13. 利用matlab聚类分析,利用Matlab软件实现聚类分析
  14. 可以搜java题目答案的网站_百度一道笔试题目的答案
  15. 关于写好一篇英文学术论文(及搞好本领域学术研究)的一些想法
  16. c语言音乐程序天空之城,51单片机演奏天空之城 c语言源程序
  17. 2021-08-07LabVIEW编程LabVIEW控制FS400308系列气体质量流量计例程与相关资料
  18. excel多列多行堆叠成多列一行_excel行列转换-Excel一行转多行、一列转多列,记住这4条可套用的模板公式...
  19. the volume for a file has been externally altered so that the opened file is no longer valid
  20. 在菲律宾人民币换php怎么换,菲律宾汇率换算人民币(人民币兑换比索计算器)

热门文章

  1. java版b2b2c社交电商spring cloud分布式微服务-服务提供与调用
  2. Android:ListView的拓展与进阶
  3. thinkphp 手机号和用户名同时登录
  4. PHP手机获取6为不反复验证码
  5. 服務端的EIT造形+Socket代碼
  6. 用SHELL脚本自动化安装Nagios服务器端和客户端的
  7. java开发实战经典学习笔记第2部分
  8. WebbUpload的验证问题
  9. ETL工具学习以及安装部署
  10. 蓝桥杯 ADV-204 算法提高 快速幂