当前位置: 首页 > news >正文

设计模式之Adapter模式

说起Adapter,STL里的stack和queue都是adapter,底层是deque,隐藏了deque的一些接口,使得其可以达到FIFO是queue,LIFO是stack。

The STL stack is a container adaptor. That is, it is not a "first-class" container, but instead simply "adapts" one of the sequential first-class containers (by default, the deque) for its own purposes. So, the deque interface is restricted (i.e., much of it is hidden) so that the required LIFO (Last In, First Out) stack-like behavior is provided.

再说通透一点,adapter就是适配器,电源适配器知道吧,把220v交流电转换为笔记本可接受的电压和电流就是我们常见的电源适配器,手机电源适配器等等。

还有STL里本来就有一类叫做adapter,有容器adapter即stack和queue,还有迭代器的adapter,有insert iterators,reverse iterators,iostream iterators,还有仿函数的functor adapters,我印象比较深的仿函数adapter就是,可以给二元操作给一个参数也能用,等等。。STL里都写的比较清楚。这里就不赘述了。

 

正题:

Adapter适配器模式是将两个不兼容的类组合在一起使用。适配器起到一种转换和包装的作用。

Adapter设计模式主要目的组合两个不相干类,常用有两种方法:第一种解决方案是修改各自类的接口。但是如果没有源码,或者不愿意为了一个应用而修改各自的接口,则需要使用Adapter适配器,在两种接口之间创建一个混合接口。

Adapter适配器设计模式中有3个重要角色:被适配者Adaptee,适配器Adapter和目标对象Target。其中两个现存的想要组合到一起的类分别是被适配者Adaptee和目标对象Target角色,我们需要创建一个适配器Adapter将其组合在一起。

实现Adapter适配器设计模式有两种方式:组合(compositon, has-a关系)和继承(inheritance,is-a关系)。

对象适配器模式使用组合,UML图如下:

利用组合实现的Adapter模式:

就是Aapter里实际上包含一个被适配的对象。(组合)又继承了target。因此如果要用到target的方法,直接调用父类的方法,如果要用到被适配者的方法, 就调用内部成员的函数。

//圆形,目标对象
class Cirecle{
    public void drawCircle(){
    System.out.println(“Draw circle”);
}
}
//方形,被适配对象
class Square{
    public void drawSquare(){
    System.out.println(“Draw square”);
}
}
//既可以画圆形,又可以画方形,适配器
public class HybridShape extends Circle{
    private Square square;
    public HybridShape(Square square){
    this.square = square;
}
public void drawSquare(){
    square.drawSquare();
}
} 


interface ICircle{
    public void drawCircle();
}
interface ISquare{
    public void drawSquare();
}
//圆形
class Cirecle implements ICircle{
    public void drawCircle(){
    System.out.println(“Draw circle”);
}
}
//方形
class Square implements ISquare{
    public void drawSquare(){
    System.out.println(“Draw square”);
}
}
//既可以画圆形,又可以画方形,适配器
public class HybridShape implements ICircle, ISquare{
    private ISquare square;
    private ICircle circle;
    public HybridShape(Square square){
    this.square = square;
}
public HybridShape(Circle circle){
    this.circle = circle;
}
public void drawSquare(){
    square.drawSquare();
}
public void drawCircle(){
    circle.drawCircle();
}
} 

利用多继承方式实现Adapter模式,java里不支持多继承,但是可以用interface实现。

先上类图:

可以看到Adapter同时继承了target和adaptee。

 4 //目标接口类,客户需要的接口
 5 class Target
 6 {
 7 public:
 8     Target();
 9     virtual ~Target();
10     virtual void Request();//定义标准接口
11 };
12 
13 //需要适配的类
14 class Adaptee
15 {
16 public:
17     Adaptee();
18     ~Adaptee();
19     void SpecificRequest();
20 };
21 
22 //类模式,适配器类,通过public继承获得接口继承的效果,通过private继承获得实现继承的效果
23 class Adapter:public Target,private Adaptee
24 {
25 public:
26     Adapter();
27     ~Adapter();
28     virtual void Request();//实现Target定义的Request接口
29 };



 6 Target::Target()
 7 {}
 8 
 9 Target::~Target()
10 {}
11 
12 void Target::Request()
13 {
14     cout << "Target::Request()" << endl;
15 }
16 
17 Adaptee::Adaptee()
18 {
19 }
20 
21 Adaptee::~Adaptee()
22 {
23 }
24 
25 void Adaptee::SpecificRequest()
26 {
27     cout << "Adaptee::SpecificRequest()" << endl;
28 }
29 
30 //类模式的Adapter
31 Adapter::Adapter()
32 {
33 }
34 
35 Adapter::~Adapter()
36 {
37 }
38 
39 void Adapter::Request()
40 {
41     cout << "Adapter::Request()" << endl;
42     this->SpecificRequest();
43     cout << "----------------------------" <<endl;
44 }

 

在Adapter模式的两种模式中,有一个很重要的概念就是接口继承实现继承的区别和联系。接口继承和实现继承是面向对象领域的两个重要的概念,接口继承指的是通过继承,子类获得了父类的接口,而实现继承指的是通过继承子类获得了父类的实现(并不统共接口)。在C++中的public继承既是接口继承又是实现继承,因为子类在继承了父类后既可以对外提供父类中的接口操作,又可以获得父类的接口实现。当然我们可以通过一定的方式和技术模拟单独的接口继承和实现继承,例如我们可以通过private继承获得实现继承的效果(private继承后,父类中的接口都变为private,当然只能是实现继承了。),通过纯抽象基类模拟接口继承的效果,但是在C++中pure virtual function也可以提供默认实现(effective C++中好像有?),因此这是不纯正的接口继承,但是在Java中我们可以interface来获得真正的接口继承了。

 

转载于:https://www.cnblogs.com/LUO77/p/5787279.html

相关文章:

  • 关于KMP算法理解(快速字符串匹配)
  • uva 10370 Above Average
  • linux下部署tomcat指定JDK版本编译并运行javaWEB应用
  • 个人视频发布汇总——教育改变人生
  • springmvc项目提交post表单参数乱码解决办法
  • MongoDB常用操作命令大全
  • I.MX6 android 4.2 源码下载
  • wait和waitpid详解
  • 使用WSAIoctl获取AcceptEx函数指针 [转]
  • esxi报错There is no more space for virtual disk--逻辑卷缩减!
  • Delphi 7使用自定义图标关联文件类型
  • NServiceBus---最流行的开源企业服务总线 for .Net
  • Struts2 - 常用的constant总结
  • EF-CodeFirst 继承关系TPH、TPT、TPC
  • 洛谷 P1313 计算系数 Label:杨辉三角形 多项式计算
  • JavaScript-如何实现克隆(clone)函数
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • 4个实用的微服务测试策略
  • 5、React组件事件详解
  • eclipse的离线汉化
  • ES6系列(二)变量的解构赋值
  • Java|序列化异常StreamCorruptedException的解决方法
  • learning koa2.x
  • node.js
  • Sublime text 3 3103 注册码
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • yii2中session跨域名的问题
  • 从零开始在ubuntu上搭建node开发环境
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 设计模式 开闭原则
  • 由插件封装引出的一丢丢思考
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • 终端用户监控:真实用户监控还是模拟监控?
  • 如何在招聘中考核.NET架构师
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (14)Hive调优——合并小文件
  • (173)FPGA约束:单周期时序分析或默认时序分析
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (转)Scala的“=”符号简介
  • (转)菜鸟学数据库(三)——存储过程
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .NET Core 中插件式开发实现
  • .NET 指南:抽象化实现的基类
  • .net连接oracle数据库
  • .net项目IIS、VS 附加进程调试
  • .Net中wcf服务生成及调用
  • /dev/VolGroup00/LogVol00:unexpected inconsistency;run fsck manually
  • @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思
  • @EventListener注解使用说明
  • @private @protected @public