软件设计模式之适配器模式(JAVA)

什么是适配器模式?

在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。适配器能将因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。

 

实现适配器的方式?

①对象适配器模式
-- 在这种适配器模式中,适配器容纳一个它包裹的类的实例。在这种情况下,适配器调用被包裹对象的物理实体。
②类适配器模式
-- 这种适配器模式下,适配器继承自已实现的类(一般多重继承)。
理论性的东西看起来就是比较烦,下面来举个日常的小例子来更好的了解适配器吧
图1:三相插头                 图2:二孔插座            图3:三相插头转二相的转换器
            
看完上面三幅图,我想大家应该都一目了然了,想把三相插头插到二孔插座里,只能中间加个转换器,这里我们可以简单把它理解成我们今天要说的适配器
再回过头看看文章开始的这句话"适配器能将因为接口不兼容而不能在一起工作的类工作在一起",没错,在两个原本不能工作到一起的组件中间添加适配器,就可以把它们关联起来了。
适配器模式里面存在着3种角色:
1、目标角色(Target):也就是客户理想中想要的接口,比如三相插头,客户想找的插孔就是三孔插座(目标角色)。
2、源(Adatee):现有的接口,也就是不满足客户想要的接口,也就是这个二孔插座(源)。
3、适配器(Adapter):能将二孔插座转换成"三孔插座"的组件,也就是上图的三相插头转二相插头转化器(适配器)。
就以上面的例子,用代码来讲下适配器模式吧
首先先来说下对象适配器模式
以笔记本通电为例,大家都知道正常的笔记本电源是三相接口
ThreeSocket.java
这是一个需求接口,也就是客户期待的,也就是3种角色中的目标接口(Target)
1 package com.lcw.adapter.test;
2 
3 public interface ThreeSocket {
4     
5     //需要一个三孔插座,也就是客戶的需求
6     public void needThreeSocket();
7 
8 }

 

TwoSocket.java

这是现有的组件,也就是那个二孔插座,也就是3种角色中的源(Adatee),虽然能通电,但接口是不满足客户的需要

1 package com.lcw.adapter.test;
2 
3 public class TwoSocket {
4     // 现有的插座,只有二孔,已经有了供电功能,只是缺少了三孔接口
5     public void serverTwo() {
6         System.out.println("我是一个二孔插座,我有供电功能");
7     }
8 
9 }

 

ThreeToTwoAdapter.java

这是适配器类,它需要2孔插座来提供电,并实现三孔插座,在构造方法中传入现有组件2孔插座的对象(带电)

 1 package com.lcw.adapter.test;
 2 
 3 public class ThreeToTwoAdapter implements ThreeSocket{
 4     private TwoSocket socket;
 5     public ThreeToTwoAdapter(TwoSocket two) {
 6         this.socket=two;
 7     }
 8     //现在已经有2孔插座的对象(意味着有通电功能)
 9     @Override
10     public void needThreeSocket() {
11         socket.serverTwo();
12         System.out.println("二孔接口已转换成三孔接口,并注入电");
13     }
14     
15 }

这样一来,适配器类这个中间类就有了源(二孔插座)的效果也就是"电"

然后再实现了目标接口方法,也就是开通了三相接口,把"电"注入,这样就可以把2个本无法一起工作的类聚集到一起,类似红娘在它们之间牵了一条关系线

 

Computer.java 笔记本类,它需要的是三孔接口

 1 package com.lcw.adapter.test;
 2 
 3 public class Computer {
 4     //笔记本电脑的电源插头需求是3孔
 5     private ThreeSocket three;
 6     public Computer(ThreeSocket three){
 7         this.three=three;
 8     }
 9     public void server(){
10         System.out.println("笔记本通电成功!");
11     }
12     
13 }

 

来写个测试类

 1 package com.lcw.adapter.test;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         //现有插座两孔,已经有提供电的功能,只是缺少3孔接口
 6         TwoSocket two=new TwoSocket();
 7         //把具有通电功能的对象传递进去,目的是要开通3孔接口的通电功能
 8         ThreeSocket three=new ThreeToTwoAdapter(two);
 9         //得到一个满足笔记本电源接口且具有电的功能对象
10         Computer computer=new Computer(three);
11         three.needThreeSocket();
12         computer.server();
13     }
14 }

看下效果图:

好了,这样就把2个原本不能在一起工作的类链接到一起了。

 

接着来说下类适配器模式

类适配器顾名思义不同点在于适配器,既然突出了'类",我们一般都会联想到继承

嗯,没错,类适配器的做法就是让适配器去继承已有功能(二孔插座)的类,然后再实现期望接口(三孔插座)

具体看代码吧,除了测试类和适配器类,其他的类与上面的保持一致,这里就不再贴出

ThreeToTwoExtendsAdapter.java(适配器类)

1 package com.lcw.adapter.test;
2 
3 public class ThreeToTwoExtendsAdapter extends TwoSocket implements ThreeSocket{
4     public void needThreeSocket() {
5         this.serverTwo();
6         System.out.println("二孔接口已转换成三孔接口");
7     }
8     
9 }

Test.java(测试类)

 1 package com.lcw.adapter.test;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         //由于ThreeToTwoExtendsAdapter继承了源,所以具有源的功能(电),并实现了3孔接口
 6         ThreeSocket socket=new ThreeToTwoExtendsAdapter();
 7         //插入接口
 8         Computer computer=new Computer(socket);
 9         socket.needThreeSocket();
10         computer.server();
11     
12     }
13 }

效果依旧:

 

 

总结下:

①对象适配模式:

把"被适配者"作为一个对象组合到适配器中,以修改目标接口包装被适配者。

(例如上面例子,二孔插座就是被适配者,把对象传入适配器并实现接口方法改造)

 

②类适配模式:

通过多重继承和实现接口的方式,单一的为某个类而实现适配。

 

适配器的作用?

1、透明:通过适配器客户端可以调用统一接口,对于客户端是透明的,这样做可以更加简洁, 直接,紧凑。

2、复用:复用了现存的类,解决因环境要求不一致的问题。

3、低耦合:将目标类与源类解耦,引入一个适配器重用源类(适配器类),遵守开放-关闭原则。

 

作者:Balla_兔子
出处:http://www.cnblogs.com/lichenwei/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不准,你也好回来找我!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401543.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

表达式与运算符

表达式与运算符 表达式 与数学中的定义相似,表达式是指具有一定的值的、用运算符把常数和变量连接起来的代数式。一个表达式可以只包含一个常数或一个变量。运算符可以是四则运算符、关系运算符、位运算符、逻辑运算符、复合运算符。下表将这些运算符从高优先级到低…

Javascript 调试技巧

Javascript 调试技巧 在代码中寻找错误 1)alert 方法: 弹框提示 2)console 方法 在调试窗口上打印 JavaScript 值 3)断点调试 在浏览器开发者工具中为JS代码添加断点,让JS执行到某一特定位置停住,方便…

[POJ2157]Maze(DFS)

题目链接:http://poj.org/problem?id2157 题意:给一张地图,地图里有门和钥匙,想要开门必须集齐所有钥匙。给定起点和终点,问从起点出发能否到达终点。 爆搜floodfill,每填一次考虑是否到达终点&#xff0c…

WPF程序将DLL嵌入到EXE的两种方法

2019独角兽企业重金招聘Python工程师标准>>> WPF程序将DLL嵌入到EXE的两种方法 这一篇可以看作是《Visual Studio 版本转换工具WPF版开源了》的续,关于《Visual Studio 版本转换工具WPF版开源了》可以参看地下地址(两篇是一样的)&…

华中地区高校第七届ACM程序设计大赛——之字形矩阵【2012年5月27日】

题意&#xff1a;输入a b Right 或 a b Down ,根据输入输出之字形路径的矩阵。 1 #include <stdio.h>2 int xx[4]{0,1,-1,1},yy[4]{1,0,1,-1};3 int map[100][100],col,row,x,y,dir,steps,idx;4 char sel[10];5 void nextdir()6 {7 switch(dir)8 {9 case 0: …

Javascript 常见使用误区

Javascript常见使用误区 1&#xff09;比较运算符&#xff1a; var x 0; if (x 10) // true if (x 0) // falsevar x 10; var y "10"; if (x y) // true if (x y) // false 恒等计算符&#xff0c;同时检查表达式的值与类型var x 10; switch(x) { //执行ca…

内存泄漏和内存溢出的优化

内存泄漏&#xff1a; 对象在内存heap堆中中分配的空间&#xff0c; 当不再使用或没有引用指向的情况下&#xff0c; 仍不能被GC正常回收的情况。 多数出现在不合理的编码情况下&#xff0c; 比如在Activity中注册了一个广播接收器&#xff0c; 但是在页面关闭的时候进行unRegi…

使用ftp搭建yum源问题解决

wget 无法连接的情况 关闭linux 防火墙 1) 重启后生效 开启&#xff1a; chkconfig iptables on 关闭&#xff1a; chkconfig iptables off 2) 即时生效&#xff0c;重启后失效 开启&#xff1a; service iptables start 关闭&#xff1a; service iptables stop 需要说明的是对…

oracle文件

1、控制文件和日志文件 控制文件&#xff08;Control File&#xff09;是一个很小的二进制文件&#xff0c;用于描述和维护数据库的物理结构。在Oracle数据库中&#xff0c;控制文件相当重要&#xff0c;它存放有数据库中数据文件和日志文件的信息。Oracle数据库在启动时需要访…

Javascript this关键字 指向详解

Javascript this关键字 指向详解 面向对象语言中 this 表示当前对象的一个引用。在 JavaScript 中 this 不是固定不变的&#xff0c;它会随着执行环境的改变而改变。 1&#xff09; 单独使用&#xff0c;this 表示全局对象。 <script type"text/javascript">…

storyboard隐藏iphone软键盘

xcode 4.3.2 storyboard ** 点击软键盘的return键隐藏软键盘 .h文件定义IBAction -(IBAction)textFieldReturn:(id)sender; .m文件实现 -(IBAction)textFieldReturn:(id)sender{[sender resignFirstResponder];//关键代码 } storyboard中&#xff0c;选中文本框&#xff0c;查…

常用命令-tar 加密

2019独角兽企业重金招聘Python工程师标准>>> 在当前目录下有一个pma目录的文件夹: 1、使用tar对文件压缩加密&#xff1a; # tar -zcvf - pma|openssl des3 -salt -k password | dd ofpma.des3 完成将得到一个pma.des3的打包文件&#xff0c;用你设置的密码替换pas…

ORM SQLAlchemy 简介

对象关系映射&#xff08;Object Relational Mapping&#xff0c;简称ORM使用DB-API访问数据库&#xff0c;需要懂 SQL 语言&#xff0c;能够写 SQL 语句&#xff0c;如果不想懂 SQL&#xff0c;又想使用关系型数据库&#xff0c;可以使用 ORM,一个 ORM , 它的一端连着 Databas…

Javascript let和const

Javascript let和const 在 ES6 之前&#xff0c;JavaScript 只有两种作用域&#xff1a; 全局变量 &#xff1a; 在函数外声明的变量作用域是全局的 局部变量&#xff08;函数变量&#xff09;&#xff1a;在函数内声明的变量作用域是局部的 <script type"text/jav…

Javascript JSON格式

Javascript JSON格式 1&#xff09;什么是JSON&#xff08;JavaScript Object Notation&#xff09;&#xff1f; 是一种轻量级的数据交换格式 是独立的语言 2&#xff09;JSON 语法规则 数据为 键/值 对 数据由逗号分隔 大括号保存对象 方括号保存数组 JSON 对象&#xff…

转:OAUTH协议简介

OAUTH协议简介 原文链接 摘要&#xff1a;OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAUTH的授权不会使第 三方触及到用户的帐号信息&#xff08;如用户名与密码&#xff09;&#xff0c;即第三方无需使用用户的用户名与密…

生产库自动派送报表派送失败之重新派送

/*Description: 生产库自动派送报表派送失败之重新派送 */USE [DB] --Replace yourDBGODECLARE ProductDate nvarchar(10) N2014-01-01DECLARE FactoryCode nvarchar(10) NXDECLARE strSQL nvarchar(3000)DECLARE strCRLF nvarchar(…

java集合框架05——ArrayList和LinkedList的区别

前面已经学习完了List部分的源码&#xff0c;主要是ArrayList和LinkedList两部分内容&#xff0c;这一节主要总结下List部分的内容。 List概括 先来回顾一下List在Collection中的的框架图&#xff1a; 从图中我们可以看出&#xff1a; 1. List是一个接口&#xff0c;它继承与Co…

Javascript 函数详解

Javascript 函数详解 1&#xff09;函数声明&#xff1a; 通过关键字function定义&#xff0c;把函数作为变量来声明 函数声明后不会立即执行&#xff0c;会在我们需要的时候调用到。 <script>function myFunction(a, b) {return a * b;}// js对大小写敏感&#xff0c;…

asp.net仿搜索引擎关键字高亮.搜索高亮

以前做关键字高亮都是直接使用replace方法直接替换 如 string input"AAbCC"; string keyword"b"; inputinput.ToUpp(); keywordkeyword.ToUpp(); ss.Replace(keyword,"<font>"keyword"</font>"); 如果这样 输出: "AA…