23种设计模式(6)-适配器模式
适配器模式
1、概述
2、适配器模式的用途
3、模式中的角色
4、实现方式
5、类适配器和对象适配器的权衡
6、缺省适配模式
1、概述
适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
2、适配器模式的用途
即Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
下面是两个典型例子
3、模式中的角色
3.1 目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
3.2 需要适配的类(Adaptee):需要适配的类或适配者类。
3.3 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
4、实现方式
(1)类的适配器模式(采用继承实现)
源代码:
//目标接口,或称为标准接口
public interface Target {//普通功能public void request();
}//已存在的、具有特殊功能、但不符合我们既有的标准接口的类
public class Adaptee {public void specificRequest() {System.out.println("被适配类...我是两孔插座 具有特殊功能");}
}//适配器类,继承了被适配类,同时实现标准接口
public class Adapter extends Adaptee implements Target {@Overridepublic void request() {System.out.println("我是适配器类 我能适配任何两孔插座 让它正常工作");this.specificRequest();}}public class Client {public static void main(String[] args) {Target adapter = new Adapter(); //通过适配器调用特殊功能adapter.request(); }
}
结果:
我是适配器类 我能适配任何两孔插座 让它正常工作
被适配类…我是两孔插座 具有特殊功能
(2)对象适配器(采用对象组合方式实现)
源代码:
//目标接口,或称为标准接口
public interface Target {//普通功能public void request();
}//已存在的、具有特殊功能、但不符合我们既有的标准接口的类
public class Adaptee {public void specificRequest() {System.out.println("被适配类...我是两孔插座 具有特殊功能");}
} //适配器类,直接关联被适配类,同时实现标准接口
class Adapter implements Target {// 直接关联被适配类private Adaptee adaptee;// 可以通过构造函数传入具体需要适配的被适配类对象public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}public void request() {// 这里是使用委托的方式完成特殊功能System.out.println("我是适配器类 我能适配任何两孔插座 让它正常工作");this.adaptee.specificRequest();}
}public class Client {public static void main(String[] args) {//使用特殊功能类,即适配类, // 需要先创建一个被适配类的对象作为参数 Target adapter = new Adapter(new Adaptee()); adapter.request(); }
}
结果:
我是适配器类 我能适配任何两孔插座 让它正常工作
被适配类…我是两孔插座 具有特殊功能
从类图中我们也知道需要修改的只不过就是 Adapter 类的内部结构,即 Adapter 自身必须先拥有一个被适配类的对象,再把具体的特殊功能委托给这个对象来实现。使用对象适配器模式,可以使得 Adapter 类(适配类)根据传入的 Adaptee 对象达到适配多个不同被适配类的功能,当然,此时我们可以为多个被适配类提取出一个接口或抽象类。这样看起来的话,似乎对象适配器模式更加灵活一点。
5、类适配器和对象适配器的权衡(摘自大牛博客)
● 类适配器使用对象继承的方式,是静态的定义方式;而对象适配器使用对象组合的方式,是动态组合的方式。
对于对象适配器,一个适配器可以把多种不同的源适配到同一个目标。换言之,同一个适配器可以把源类和它的子类都适配到目标接口。因为对象适配器采用的是对象组合的关系,只要对象类型正确,是不是子类都无所谓。
● 对于对象适配器,要重定义Adaptee的行为比较困难,这种情况下,需要定义Adaptee的子类来实现重定义,然后让适配器组合子类。虽然重定义Adaptee的行为比较困难,但是想要增加一些新的行为则方便的很,而且新增加的行为可同时适用于所有的源。
● 对于类适配器,仅仅引入了一个对象,并不需要额外的引用来间接得到Adaptee。
● 对于对象适配器,需要额外的引用来间接得到Adaptee。
建议尽量使用对象适配器的实现方式,多用合成/聚合、少用继承。当然,具体问题具体分析,根据需要来选用实现方式,最适合的才是最好的。
适配器模式的优点
更好的复用性
系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。
更好的扩展性
在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。
适配器模式的缺点
过多的使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
6、缺省适配模式
缺省适配(Default Adapter)模式为一个接口提供缺省实现,这样子类型可以从这个缺省实现进行扩展,而不必从原有接口进行扩展。作为适配器模式的一个特例,缺省是适配模式在JAVA语言中有着特殊的应用。
就是一个抽象类对功能接口的所有功能做空实现 然后子类继承这个抽象类 这样就可以对部分功能进行实现或拓展了
源代码
功能接口:
/*** 功能接口 谈恋爱后具备如下功能* 牵手* 接吻* 看电影* 情侣晚餐* 回家见父母* @author Administrator**/
public interface Love {//牵手 该功能是恋爱后经常会有的波public void hand();//接吻public void kiss();//看电影public void lookMovie();//情侣晚餐public void have();//回家见父母public void backHome();//女朋友是谁public String getGirlFriend();}
缺省适配类
/*** 抽象类 * 交往类 实现恋爱接口* 哈哈 交往多了自然就谈爱了吗 嘻嘻嘻!* 但是交往毕竟不是谈恋爱 虽然它具有了谈恋爱的雏形 但是毕竟不是* 所以对谈恋爱的所有功能做了空实现 只有架子* 相当于没有 但是未来可能会有 嘎嘎嘎* @author Administrator**/
public abstract class Communication implements Love {//全是空实现 @Overridepublic void hand() {}@Overridepublic void kiss() {}@Overridepublic void lookMovie() {}@Overridepublic void have() {}@Overridepublic void backHome() {}@Overridepublic String getGirlFriend() {return null;}}
具体实现
/*** 具体的类LiangShanbo继承了交往Communication抽象类 * 本类Liangshanbo已经从交往慢慢恋爱了 所以它已经具备了谈恋爱接口* 的所有功能 但是了 有些功能他每天不可能天天都调用* 比如 看电影 情侣晚餐 回家见父母等等 * (因为分隔两地,不能天天见面 但是了 他们一见面就和过年一样高兴* 他们就可以调用恋爱中的一些功能* 比如他们 可以看电影 共进晚餐* )* * @author Administrator**/public class LiangShanbo extends Communication {//看电影public void lookMovie(){System.out.println("我们一起看电影 哈哈");}//情侣晚餐public void have(){System.out.println("我们一起吃晚餐 哈哈");}//女朋友是谁public String getGirlFriend(){return "ZhuYingtai";}
}
客户端:
public class Client {public static void main(String[] args) {Love lover = new LiangShanbo();lover.lookMovie();lover.have();System.out.println("女朋友是 :"+lover.getGirlFriend());}
}
结果:
我们一起看电影 哈哈
我们一起吃晚餐 哈哈
女朋友是:ZhuYingtai
在很多情况下,必须让一个具体类实现某一个接口,但是这个类又用不到接口所规定的所有的方法。通常的处理方法是,这个具体类要实现所有的方法,那些有用的方法要有实现,那些没有用的方法也要有空的、平庸的实现。
这些空的方法是一种浪费,有时也是一种混乱。除非看过这些空方法的代码,程序员可能会以为这些方法不是空的。即便他知道其中有一些方法是空的,也不一定知道哪些方法是空的,哪些方法不是空的,除非看过这些方法的源代码或是文档。
缺省适配模式可以很好的处理这一情况。可以设计一个抽象的适配器类实现接口,此抽象类要给接口所要求的每一种方法都提供一个空的方法。就像具体帮助类汤高一样 他只实现某一部分功能 因为他只用到了某一部分功能而已,如果以后要用,再实现其他功能就是,但是今天他不用,就没必要该功能了!
适配器模式的用意是要改变源的接口,以便于目标接口相容。缺省适配的用意稍有不同,它是为了方便建立一个不平庸的适配器类而提供的一种平庸实现。
在任何时候,如果不准备实现一个接口的所有方法时,就可以使用“缺省适配模式”制造一个抽象类,给出所有方法的平庸的具体实现。这样,从这个抽象类再继承下去的子类就不必实现所有的方法了
23种设计模式(6)-适配器模式相关推荐
- 在王者荣耀角度下分析面向对象程序设计B中23种设计模式之适配器模式
· 适配器模式在王者荣耀中的应用 · 应用一:元歌通过傀儡假扮敌方的任意英雄 应用二:王者荣耀iOS与安卓互通 一.简述 简单来讲,适配器模式就是通过一个适配器将一个类的接口变成客户端所期待的另一种接 ...
- 23种设计模式之适配器模式
适配器模式的定义 定义: 将一个类的接口变换成客户端所期待的另一种接口, 从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作. 通俗的说, 就是有 A.B两个接口, 现在要求把A和B安装在一 ...
- (六)JAVA设计模式23种设计模式之适配器模式实例demo
适配器模式 适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁.这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能. 这种模式涉及到一个单一的类,该类负责加入独立的 ...
- 23种设计模式之适配器模式(Adapter)
适配器模式将一个接口转换成客户希望的另一个接口,从而使接口不兼容的那些类可以一起工作.适配器模式既可以作为类结构型模式,也可以作为对象结构型模式.在类适配器模式中,通过使用一个具体类将适配者适配到目标 ...
- 23种设计模式之模板方法
23种设计模式总篇:chenmingyu.top/design/ 模板方法 模板方法属于行为型模式 定义:定义一个操作中的算法的框架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重定 ...
- Java开发中的23种设计模式详解(转)
设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- 【设计模式】Java 23种设计模式对比总结
一.设计模式的分类 创建型模式,共五种(1-5):工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种(6-12):适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组 ...
- 23种设计模式C++实现UML+源码汇总
设计模式-汇总 代码开源仓库地址 23种设计模式C++实现 C++中的开闭原则使用C++多态功能实现附源码 C++基于多态实现依赖颠倒原则附源码 C++ 的静态成员变量为什么一定要在类外定义 23种设 ...
- 【java】java开发中的23种设计模式详解
设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
最新文章
- 花了我一个晚上浓缩了一整套阿里资深技术专家设计教程整理出的java架构设计方法
- python游戏-练习项目19:使用python制作游戏(上)
- 使用Properties集合存储数据,遍历取出Properties集合中的数据
- sohu读博——周忆清
- 企业网络之间资源互访
- bgb邻居关系建立模型_知识图谱上的双塔召回:阿里的IntentGC模型
- java 上溯造型与下塑造型
- windows7安装openssh
- 来自IT公司速查手册的各大IT公司薪资和待遇内幕
- element-ui 下拉框实现拼音搜索
- python 爬手机号_【Python爬虫】手机号网段爬虫
- android 热点 连接电脑上网,安卓手机做wifi热点让笔记本上网的方法
- 线性代数及矩阵论(八)
- adaboost.M1与adaboost.M2差别比较
- python变量命名规则
- 腾讯产品/策划笔试面试经验
- flow java.lang.IllegalArgumentException: Unable to create call adapter for
- solr常见问题整理
- windows10利用docker安装splash
- CobaltStrike二次开发环境准备以及免杀