软件秘笈-设计模式那点事_第7章 电源转换:适配器模式
- 格式:pdf
- 大小:529.68 KB
- 文档页数:11
java设计模式-适配器模式java适配器模式1、概述 什么是适配器模式? 适配器模式是⼀种结构型设计模式。
适配器模式就是:把⼀个类的接⼝变换成客户端所期待的另⼀种接⼝,从⽽使原本因接⼝不匹配⽽⽆法在⼀起⼯作的两个类能够在⼀起⼯作。
⽤电器来打个⽐喻:有⼀个电器的插头是三脚的,⽽现有的插座是两孔的,要使插头插上插座,我们需要⼀个插头转换器,这个转换器即是适配器。
适配器模式涉及3个⾓⾊:源(Adaptee):需要被适配的对象或类型,相当于插头。
适配器(Adapter):连接⽬标和源的中间对象,相当于插头转换器。
⽬标(Target):期待得到的⽬标,相当于插座。
2、适配器模式UML图 图⽚来⾃⽹络 通过上⾯UML图可以知道,客户端期待的接⼝或者对象通过适配器的转换得到了满⾜,Adapter通过内部包装Adaptee对象把源对象转换成客户端期待的对象。
3、适配器模式分类 适配器模式包括3种形式:1. 类适配器模式:类适配器使⽤的是继承的⽅式,⼀般来说⽆法对其⼦类进⾏适配2. 对象适配器模式:对象适配器使⽤的是组合的⽅式,⼦孙类都可以被适配。
另外,对象适配器对于增加⼀些新⾏为⾮常⽅便,⽽且新增加的⾏为同时适⽤于所有的源。
3. 接⼝适配器模式(⼜称缺省适配器模式):接⼝适配器模式(缺省适配模式)基本思想是,为⼀个接⼝提供缺省实现,这样⼦类可以从这个缺省实现进⾏扩展,⽽不必从原有接⼝进⾏扩展。
可以说对象适配器模式是另外6种结构型设计模式的起源(图⽚源⾃⽹络)。
4、三种适配器模式详解 适配器模式的三种实现⽅式及代码实例详解,⽤电器来打个⽐喻:有⼀个电器的插头是两脚的,⽽现有的插座是三孔的,要使插头插上插座,我们需要⼀个插头转换器,这个转换器即是适配器。
图⽚源⾃⽹络4.1、类适配器模式 类适配器使⽤的是继承的⽅式,⼀般来说⽆法对其⼦类进⾏适配,请看代码实例 1.⾸先我们有⼀个要被适配的类/*** 源(相当于两脚插头,也就是被适配的类)* @author ningbeibei*/public class Adaptee {public void adapteeMethod() {System.out.println("两脚插头,被适配的类....");}} 2.定义⼀个⽬标接⼝/*** ⽬标(客户所期待的类,可以是⼀个接⼝抽象类具体的类)* 相当于三孔插板* @author ningbeibei*/public interface Target {void targetMethod(); 3.定义适配器类 定义适配器类通过继承 Adaptee 和实现 Target 接⼝关联起来,/*** 类适配器模式(相当于转换器)* 通过Adapter类把Adaptee类与Target接⼝衔接起来* @author ningbeibei*/public class Adapter extends Adaptee implements Target {@Overridepublic void targetMethod() {//操作处理adapteeMethod();//操作处理}} 4.测试代码/*** 适配器模式测试类* @author ningbeibei*/public class test {public static void main(String[] args) {//类适配器模式Adapter adapter = new Adapter();adapter.targetMethod();}} 5.运⾏结果4.2、对象适配器模式 对象适配器使⽤的是组合的⽅式,它把源类作为属性放⼊适配器类中,请看代码实例 1.定义被适配的类/*** 源(相当于两脚插头,也就是被适配的类)* @author ningbeibei*/public class Adaptee {public void adapteeMethod() {System.out.println("两脚插头,被适配的类....");}} 2.定义⽬标接⼝/*** ⽬标(客户所期待的类,可以是⼀个接⼝抽象类具体的类)* 相当于三孔插板* @author ningbeibei*/public interface Target {void targetMethod();} 3.定义适配器类(类似于转换器) 注意:通过持有Adaptee属性建⽴与Target接⼝联系/*** 对象适配器模式(相当于转换器)* 通过持有Adaptee属性建⽴与Target接⼝联系* @author ningbeibei*/public class Adapter implements Target {//添加属性private Adaptee adaptee;public Adapter (Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void targetMethod() {//操作处理adaptee.adapteeMethod();//操作处理} 4.测试类/*** 适配器模式测试类* @author ningbeibei*/public class test {public static void main(String[] args) {//对象适配器模式Adapter adapter = new Adapter(new Adaptee());adapter.targetMethod();}} 5.结果输出4.3、接⼝适配器模式(缺省适配模式) 接⼝适配器模式⼜称缺省模式,这种模式通过抽象类对接⼝进⾏实现,在抽象类种对接⼝进⾏默认实现。
Java设计模式--适配器模式详解⽬录定义结构⽰例扩展总结定义适配器模式⽤于解决接⼝间的兼容问题。
当我们需要使⽤某个类提供的接⼝,但是这个接⼝与现在的系统需求不符,由于该接⼝是由第三⽅提供的,或者是已经在⽣产上跑了很久的存量类,我们不想通过改变这个类来满⾜现在系统的需求,那么这时候就可以考虑通过将⽬标类封装成⼀个满⾜系统需求的新类,因此适配器(Adapter)也称为包装器(Wrapper)。
结构适配器模式包含如下⾓⾊:Target:⽬标抽象类,客户类期望的接⼝。
Adapter:适配器类,适配器模式的核⼼,实现⽬标抽象类和适配者类的转换。
Adaptee:适配者类,与⽬前需求不兼容的类,即需要被包装的类。
Client:客户类,调⽤在⽬标抽象类中定义的业务⽅法。
适配器模式有类适配器和对象适配器两种实现:1、在类适配器模式中,适配器类实现了⽬标抽象类接⼝并继承了适配者类,在⽬标抽象类的实现⽅法中调⽤所继承的适配者类的⽅法。
2、在对象适配器模式中,适配器类实现了⽬标抽象类并定义了⼀个适配者类的对象实例,在⽬标抽象类的实现⽅法中调⽤适配者类实例的⽅法。
⽰例假如我们⼿上有⼀只⼿机,它只有⼀个type-c接⼝,同时⼿上有⼀条3.5mm的⽿机,想听⾳乐的时候就会发现⼆者不兼容,相较于更换⼿机或者⽿机,⼀般我们会选择⼀条type-c和3.5mm的转接线来实现最⾼性价⽐。
此时将3.5mm⽿机⽐作客户端(客户类),它期望得到⾳乐信号的⽬标是3.5mm接⼝(⽬标抽象类),type-c接⼝则是⼿机提供的⾳乐信号传输接⼝(适配者类),与⽿机接头不兼容,⽽转接线(适配器类)可以将type-c接⼝包装为⽿机可以插⼊的3.5mm接⼝,能够解决⼿机与⽿机的不兼容问题,实现⽤⽿机接收⼿机播放的⾳乐信号。
1、定义⽬标抽象类,即客户类期望的接⼝。
public interface ThreePointFiveConn {//⼀个提供⾳乐的3.5mm接⼝public void playMusic(String connector);}2、定义适配者类,即需要被包装的类。
Adapter适配器模式是一种结构型模式,主要应对:由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是,新环境要求的接口是现存对象所不满足的。
《设计模式》中说道:将一个类的接口转换成客户希望的另一个接口。
Adapter模式使得原本由于接口不兼容而不能一起工作的类可以一起工作。
在实际的生活中有很多例子,如:我们常使用的移动硬盘,无论是笔记本硬盘还是台式机硬盘,对于数据的传输都不使用Usb的数据线,外接的硬盘盒就是将原来的硬盘数据传输方式适合Usb数据线。
(哎,我那个硬盘盒买的时候还190元,其实一点都不值,整个一个盒,就那个转接芯片比较值钱,我说50,人家不卖)。
我再接着说适配器模式,先举个简单的代码例子,我现在要做一个队列的类,实现先进先出的功能。
利用ArrayList对象。
首先,我们先定义一些队列的接口,接口中定义队列的方法,代码如下:interface IQueue{void push(object item); //进队列object putout(); //出队列object ShowLastItem(); //返回队列中最后一项object ShowFirstItem(); //返回队列中第一项}下面我们再来利用ArrayList对象实现一个队列:class Queue:IQueue{ArrayList adaptee;public Queue(){adaptee = new ArrayList();}publicvoid push(object item){adaptee.Add(item);}publicobject putout(){object item = adaptee[0];adaptee.RemoveAt(0);return item;}publicobject ShowLastItem(){return adaptee[adaptee.Count-1];}publicobject ShowFirstItem(){return adaptee[0];}}实现有了,现在用客户端程序调用来看一下结果:class Class1{///<summary>///应用程序的主入口点。
注:文档内容基本上来自于网上,并加上自己的理解而成。
有的觉得网友总结得非常好,就完全照搬下来,供学习之用。
然而,有的摘抄并没有加上原链接和出处,请谅解。
适配器模式解决的问题是接口不兼容问题。
5.3 适用场景5.3.1 系统需要使用现有的类,而这些类的接口不符合系统的接口。
5.3.2 想要建立一个可以重用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
5.3.3 两个类所做的事情相同或相似,但是具有不同接口的时候。
5.3.4 旧的系统开发的类已经实现了一些功能,但是客户端却只能以另外接口的形式访问,但我们不希望手动更改原有类的时候。
5.3.5 使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己的接口,但是要使用第三方组件接口的功能。
1. 概述将一个类的接口转换成客户希望的另外一个接口。
Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
2. 解决的问题即Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
3. 模式中的角色3.1 目标接口(Target):客户所期待的接口。
目标可以是具体的或抽象的类,也可以是接口。
3.2 需要适配的类(Adaptee):需要适配的类或适配者类。
3.3 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
4. 模式解读注:在GoF的设计模式中,对适配器模式讲了两种类型,类适配器模式(多继承)和对象适配器模式(组合)。
由于类适配器模式通过多重继承对一个接口与另一个接口进行匹配,而C#、java等语言都不支持多重继承,因而这里只是介绍对象适配器。
即也可以说成实现适配器模式在有两种方式,一是通过继承,二是通过组合。
在支持多继承的语言中,例如C++,能过继承方式来实现对多个类提供统一接口的适配器模式有时候非常方便。
如果语言不支持多继承,则通过组合形式的对像适配方式来实现。
实验(上机)六适配器模式实验(上机)目的1、练习使用结构型设计模式;2、练习使用适配器模式的设计思路;3、练习使用适配器模式实现“教务学生成绩排序查找”案例的实现。
实验(上机)课时2学时实验(上机)环境JDK1.8\Eclipse Mars预备知识1、结构型模式;2、适配器模式概述;3、适配器模式的结构与实现;4、适配器模式的应用实例;5、缺省适配器模式;6、双向适配器模式;7、适配器模式的优缺点与适用环境。
实验(上机)内容在为某学校开发教务管理系统时,开发人员发现需要对学生成绩进行排序和查找,该系统的设计人员已经开发了一个成绩操作接口ScoreOperation,在该接口中声明了排序方法Sort(int[]) 和查找方法Search(int[], int),为了提高排序和查找的效率,开发人员决定重用现有算法库中的快速排序算法类QuickSortClass和二分查找算法类BinarySearchClass,其中QuickSortClass的QuickSort(int[])方法实现了快速排序,BinarySearchClass的BinarySearch (int[], int)方法实现了二分查找。
由于某些原因,开发人员已经找不到该算法库的源代码,无法直接通过复制和粘贴操作来重用其中的代码;而且部分开发人员已经针对ScoreOperation接口(自己开发的接口)编程,如果再要求对该接口进行修改或要求大家直接使用QuickSortClass类和BinarySearchClass类将导致大量代码需要修改。
现使用适配器模式设计一个系统,在不修改已有代码的前提下将类QuickSortClass 和类BinarySearchClass的相关方法适配到ScoreOperation接口中。
新建解决方案,新建一个控制台应用程序,编写适配器模式类实现代码,实现以上需求的案例,要求编写为控制台应用程序,并能调试运行。
JAVA设计模式之适配器模式1 初步认识适配器模式的定义 将⼀个类的接⼝转成客户期望的另外⼀个接⼝。
适配器模式使得原本由于接⼝不匹配⽽不能⼀起⼯作的那些类可以⼀起⼯作。
⼤⽩话 适配器模式就像旅⾏插座转换器(图1)、Type-c转VGA转接⼝(图4)⼀样。
图1. 图⽚来源⽹络图2. 图⽚来源⽹络 去过⾹港迪拜等的同学都知道,那边⽤的插座跟我们不⼀样,他们的插座需要如图2第1⾯所⽰的插头,⽽我们常⽤的插座类似第2⾯。
因此我们的笔记本电脑,⼿机在当地不能直接充电。
所以就需要⼀个插座转换器,转换器第1⾯插⼊当地的插座,第2⾯供我们充电,这样使得我们的插头在当地能使⽤。
Type-c转VGA转接⼝也是⼀样的道理。
2 适配器模式结构图图3. 适配模式结构图来源⽹络 如图所⽰,Client不能直接访问Adaptee。
Adapter是适配器,它将Adaptee转换成Client能访问的接⼝。
所以通过适配器Adapter,⽤户端就可以访问Adaptee。
3 使⽤场景例⼦ ⼿机想要投影到投影仪上,由于⼿机是Type-c接⼝,投影仪是VGA接⼝。
不能直接投影,需要⼀个适配器,将视频信号从Type-c⼝转到VGA⼝,最后才能输出到⼤屏幕上。
4 适配器模式在使⽤场景的具体实现图4. typec转vga/hdm转换器 如图所⽰,这有⼀个适配器,⼀号⼝是typec⼝,⼆号⼝是vga⼝,只有将视频信号从typec⼝输⼊,转换输出到vga⼝,才能和投影仪对接,实现⼿机屏幕投影到投影仪上的任务。
涉及的物品有:⼿机、适配器、投影仪。
4.1 定义⼀个⼿机,它有个typec⼝,这是视频源。
package com.jstao.adapter;/*** @author jstao* 定义⼀个⼿机Phone,它有⼀个Typec接⼝。
**/public class Phone {public void typecPhone() {System.out.println("信息从Typec⼝的⼿机输出。
JAVA设计模式详解(五)----------适配器模式 各位朋友好,本章节我们继续讲第五个设计模式。
在⽣活中,我们都知道⼿机内存卡是⽆法直接接电脑的,因为内存卡的卡槽⽐较⼩,⽽电脑只有USB插孔,此时我们需要⽤到读卡器。
这个读卡器就相当于是适配器。
这是⽣活上的适配器,那么在OO对象中,适配器就是将⼀个接⼝转换成另⼀个接⼝,使得客户可以使⽤。
适配器模式从实现⽅式上分为两种,类适配器和对象适配器,这两种的区别在于实现⽅式上的不同,⼀种采⽤继承,⼀种采⽤组合的⽅式。
下⾯我们来看⼀个例⼦,下⾯有两个接⼝,⼀个是⿅(Deer),⼀个是狼(wolf),public interface Deer {public void run();public void eatGrass();}interface Wolf{public void run();public void eatMeat();}我们让梅花⿅(SikaDeer)和雪狼(SnowWolf)分别实现这两个接⼝class SikaDeer implements Deer{@Overridepublic void run() {System.out.println("我在跑");}@Overridepublic void eatGrass() {System.out.println("我在吃草");}}class SnowWolf implements Wolf{@Overridepublic void run() {System.out.println("我在跑");}@Overridepublic void eatMeat() {System.out.println("我在吃⾁");}}假设现在狼要吃⿅,但是他要伪装成⿅然后混进去,那么现在因为接⼝不同,⽆法伪装,所以现在我们帮它写个适配器:class SnowAdapter implements Deer{//⾸先我们需要实现想转换成的接⼝,也就是⿅要看到的接⼝private SnowWolf snowWolf;public SnowAdapter(SnowWolf snowWolf) {this.snowWolf = snowWolf;//接着取得我们要适配的对象的引⽤}@Overridepublic void run() {snowWolf.run();//接着实现接⼝的⽅法}@Overridepublic void eatGrass() {snowWolf.eatMeat();}}接下来我们写个测试类:public class TestAdapter {public static void main(String[] args) {Deer sikaDeer = new SikaDeer();//先来个梅花⿅SnowWolf snowWolf = new SnowWolf();//再来个雪狼SnowAdapter snowAdapter = new SnowAdapter(snowWolf);//接下来是伪装后的雪狼System.out.println("snowWolf:");snowWolf.run();snowWolf.eatMeat();System.out.println("sikaDeer says:");testDeer(sikaDeer);System.out.println("snowAdapter says:");testDeer(snowAdapter);}public static void testDeer(Deer deer){deer.run();deer.eatGrass();}}结果展⽰:在这⾥,我们来分析⼀下这个过程,⿅是我们的⽬标接⼝,梅花⿅是依据⿅实现的,⽽适配器实现了⽬标接⼝,并持有被适配者(雪狼)的实例。