`

三十二:适配器模式

阅读更多
适配器模式把一类的接口变成客户端所期待的另一个接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作.

一:名字的由来
这很像变压器(Adapter),变压器把一种电压变成另一种电压。把美国的电器拿回中国大陆用的时候,用户就面临电压不同的问题。美国的生活用电电压是110V,而中国的电压是220V,如果要在中国使用美国的电器,就必须有一个能把220V电压转换成110V电压的变压器,而这正是本模式所做的事。

前面提到适配器模式有两种,下面一一介绍:

二:类的适配器模式
类的适配器模式把被适配的类的API转换成为目标类的API,此模式所涉及的角色有:
(A)目标(Target)角色:这就是所期待得到的接口(注:由于这里讨论的是类适配器模式,因此目标不可以是类)
(B)源(Adaptee)角色:现在需要适配的接口
(C)适配器(Adapter)角色:适配器类是本模式的核心,它把源接口转换成目标接口,显然这一角色不可以是接口,而必须是具体类
源代码如下:
package cai.milenfan.basic.test; 
public interface Target { 
//这是源类也有的方法
void sampleOperation1(); 
//这是源类不有的方法
void sampleOperation2(); 
} 

package cai.milenfan.basic.test; 
public class Adaptee { 
public void sampleOperation1(){ 
//....your code 
} 
} 

package cai.milenfan.basic.test; 
public class Adapter extends Adaptee implements Target{ 
//由于源类没有这个方法,因此适配器类补充这个方法
public void sampleOperation2() { 
} 
} 

由上知,Adatee类并没有sampleOperation2()方法,而客户端则期待这个方法,为使客户端能够使用Adaptee类,提供一个中间五一节,即类Adapter,把Adaptee的API与Target类的API衔接起来,Adapter与Adaptee是继承关系,这决定了这个适配器是类.
效果分析:
a.使用一个具体类把源(Adaptee)适配到目标(Target)中,这样一来,如果源以及源的子类都使用此类适配,就行不通了。
b.由于适配器类是源的子类,因此可以在适配器类中置换掉(Override)源的一些方法
c.由于只引进了一个适配器类,因此只有一个路线到达目标类,使问题得到简化.

三:对象的适配器模式
与类的适配器模式一样,对象的适配器模式把被适配的类的API转换成目标类的API,与类的适配器不同的是,对象的适配器不是使用继承关系连接到Adaptee类,而是使用委派关系连接到Adaptee类,它所需要的角色和类的适配器模式相同,下面是源代码:
package cai.milenfan.basic.test; 
public interface Target { 
//这是源类也有的方法
void sampleOperation1(); 
//这是源类不有的方法
void sampleOperation2(); 
} 


package cai.milenfan.basic.test; 
public class Adaptee { 
public void sampleOperation1(){ 
//....your code 
} 
} 

package cai.milenfan.basic.test; 
public class Adapter implements Target{ 
private Adaptee adaptee; 
public Adapter(Adaptee adaptee){ 
super(); 
this.adaptee = adaptee; 
} 
//源类有方法,适配器直接委派即可
public void sampleOperation1() { 
adaptee.sampleOperation1(); 
} 
//源类没有这个方法,因此适配器类需要补充此方法
public void sampleOperation2() { 
//write your code here..... 
} 
} 


请不要误认为适配器模式就是为了补充源角色没有的方法而准备的哦! !
效果分析:
a.一个适配器可以把多种不同的源适配到同一个目标,换言之,同一个适配器可以把源类和它的子类都适配到目标接口
b.与类的适配模式相比,要想置换源类的方法就不容易。如果一定要置换源类的一个或多个方法,就只好先做一个源类的子类,将源类的方法置换掉,然后再把源类的子类当做真正的源进行适配。
c.虽然要想置换源类的方法不容易,但是要想增加一些新的方法则方便得很,而且新增的方法可同时适用于所有的源.

四:在什么情况下使用适配器模式
(1)系统需要使用现有的类,而此类的接口不符合系统的需要。
(2)想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类
(3)(对对象的适配器模式而言)在设计里,需要改变多个已有的子类的接口,如果使用类的适配器模式的话,就要针对每一个子类做一个适配器类,而这不太实际.

五:利用适配器模式指方(Cube)为圆(BallIF)
package cai.milenfan.basic.test; 
public class Cube { 
private double width; 
public Cube(double width){ 
this.width = width; 
} 
//计算体积
public double calculateVolume(){ 
return width*width*width; 
} 
//计算面积
public double calculateFaceArea(){ 
return width*width; 
} 
public double getWidth() { 
return width; 
} 
public void setWidth(double width) { 
this.width = width; 
} 
} 

package cai.milenfan.basic.test; 
public interface BallIF { 
//计算面积
double calculateArae(); 
//计算体积
double calculateVolume(); 
//半径的get/set 
double getRadius(); 
void setRadius(double radius); 
} 


package cai.milenfan.basic.test; 
public class MagicFinger implements BallIF{ 
private double radius = 0; 
private static final double PI = 3.14d; 
private Cube adaptee; 
public MagicFinger(Cube adaptee){ 
super(); 
this.adaptee = adaptee; 
radius = adaptee.getWidth(); 
} 
public double calculateArae() { 
return PI * 4.0d * (radius * radius); 
} 
public double calculateVolume() { 
return PI * 4.0d/3.0d * (radius * radius * radius); 
} 
public double getRadius() { 
return radius; 
} 
public void setRadius(double radius) { 
this.radius = radius; 
} 
} 


上面的MagicFinger接收一个正方体,返回此正方体的内切球,本例用的是对象的适配器模式,(相对于类的适配模式)这样做的好处是,如果一旦决定不仅要支持正方体,而且要支持四面体等多面体,可以使用同一个MagicFinger类,而不必对每一个多面体建立一个MagicFinger类。

六:适配器模式在层次上的应用
(1)wine是一个免费软件,它允许用户在Linus环境里运行Window程序,可以知道,Wine提供了从Linux到Window图形界面的适配器,它使得Windows的图形界面可以在Linux界面里运行,这样不必修改任何一个图形界面,便可以使两者兼容。
(2)jdbc驱动软件
JDBC给出了一个客户端通用的界面,每一个数据库引擎的JDBC驱动软件都是一个介于JDBC接口和数据库引擎接口之间的适配器软件,如下图:

<--------------------Oracle JDBC------------Oracle
------------------
JDBC <--------------------SQLServer JDBC--------------SQLServer
------------------
<--------------------MySQL JDBC--------------MySQL
抽象的JDBC接口和各个数据库引擎的API之间都需要相应的适配器软件,即为数据库引擎准备的驱动软件.
(3)jdbc/odbc桥梁
java application-->jdbc driver manager-->jdbc/odbc bridge-->odbc driver-->DB
jdbc的库不可能和odbc的库有相同的接口,因此使用适配器模式将odbc的API接口改为jdbc的接口就是唯一可行的办法,因此jdbc/odbc bridge是适配器模式的应用.

七:模式实现的讨论
本模式需要注意的地方有:
(1)目标接口可以省略,此时目标接口和源接口实际上是相同的,由于源是一个接口,而适配器是一个类,因此这种做法看似平庸而并不平庸,它可以使客户端不必实现不需要的方法(这将在缺省适配的情况下看到)
(2)适配器类可以是抽象的(这将在缺省适配的情况下看到)
(3)带参数的适配器模式,使用这种办法,适配器可以根据参数返回一个合适的实例给客户端.

八:适配器模式和相关的模式(跳过)
分享到:
评论

相关推荐

    实验七:适配器模式.rar

    适配器模式是一种软件设计模式,它允许两个不兼容的接口之间进行通信。在本实验中,我们将深入探讨适配器模式的概念、应用场景以及如何在实际编程中实现它。适配器模式通常分为类适配器和对象适配器两种形式。 ...

    第十六讲:适配器模式

    在软件工程中,当系统中存在一个已经存在的组件或者第三方库,但其接口与我们新设计的系统不匹配时,适配器模式就显得尤为重要。适配器模式通过创建一个新的类(适配器类)来包装原有接口,从而使得新系统能够调用...

    Python 程序语言设计模式思路-结构型模式:适配器模式-将不兼容的接口转换为可兼容的接口

    2. 第三方库集成:在使用第三方库时,适配器模式可以将第三方库的接口转换为应用程序内部统一的接口,简化集成过程。 3. 接口统一:在系统中使用多个接口不兼容的类时,适配器模式可以将这些接口统一起来,提供一致...

    23种设计模式--适配器模式

    适配器模式是一种软件设计模式,它允许两个不兼容的接口之间进行通信。在软件工程中,这种模式常被用来解决旧系统与新系统、第三方库或者不同组件之间的接口不匹配问题。适配器模式的核心思想是通过创建一个新的类...

    java设计模式之适配器模式

    二、适配器模式的结构 适配器模式主要涉及四个角色: - 目标接口(Target):客户端所期待的接口。 - 适配者类(Adaptee):需要适配的原有接口或类。 - 适配器(Adapter):实现了目标接口,并持有适配者类的实例,...

    适配器模式案例代码

    适配器模式是一种软件设计模式,它允许两个不兼容的接口之间进行通信。在这个案例中,我们关注的是如何通过适配器模式解决实际编程问题。文章《适配器模式案例代码》提供了具体的实现示例,链接指向了CSDN博主...

    设计模式的适配器模式的例子

    适配器模式是一种常用的设计模式,它在软件工程中扮演着重要的角色,允许不同接口的类之间进行通信。适配器模式的核心思想是将一个类的接口转换成客户期望的另一个接口,使得原本由于接口不兼容而无法一起工作的类...

    设计模式之适配器模式

    1. 类适配器模式:在这种模式下,适配器类继承了适配者类,并实现了目标接口。这样,适配器可以直接调用适配者类的方法,同时通过实现目标接口的方法来完成转换工作。 2. 对象适配器模式:适配器类不继承适配者类,...

    .Net设计模式_适配器模式

    1. 类适配器模式:适配器类继承自待适配的类,并且实现目标接口。在.NET中,这意味着适配器类会扩展待适配类的功能,同时提供符合目标接口的方法。这种方式的优势在于可以利用继承的多态性,但缺点是无法适应多个...

    设计模式-适配器模式(讲解及其实现代码)

    1. 类适配器模式:适配器类继承自原始接口或类,并实现新的目标接口。这种方式适用于目标接口和原始接口都是类的情况,但缺点是如果原始接口有多个,继承会导致类层次复杂。 2. 对象适配器模式:适配器类包含一个...

    适配器模式源代码

    3. 接口适配器模式:当目标接口有多个方法,而被适配者只实现了其中一部分时,可以通过接口适配器提供默认实现,让被适配者只需关注自己需要实现的部分。 适配器模式的步骤通常包括: 1. 定义目标接口,这是客户端...

    JAVA设计模式(抽象类与适配器模式)

    今天我们要探讨的是JAVA设计中的两个重要模式:抽象类与适配器模式。 首先,我们来理解一下“抽象”。抽象是面向对象编程的核心概念之一,它帮助我们处理对象的复杂性。在Java中,抽象通常通过抽象类来实现。抽象类...

    设计模式之--适配器模式

    例如,在软件开发中,当需要将一个第三方库的API与自己项目中的接口进行对接时,适配器模式可以帮助我们平滑过渡,减少对接带来的复杂性。 在实际应用中,适配器模式可能涉及的步骤包括: 1. 确定目标接口,这是...

    设计模式 - 适配器模式(C++实例)

    1. 类适配器模式: 在类适配器模式中,适配器类继承自目标接口,并且通常也包含对原始不兼容接口的引用。适配器类通过重写或实现目标接口的方法,调用原始接口的方法,从而达到接口转换的目的。这种方式在C++中常见...

    设计模式之适配器模式Java实现和类设计图

    文件列表中的"adapter"可能包含了适配器模式的Java源代码文件,这些文件通常会包含以上提到的三个角色的定义。例如,可能会有`Target.java`(目标接口),`Adaptee.java`(被适配者类),以及`Adapter.java`(类...

    C#面向对象设计模式纵横谈(7):Adapter 适配器模式(结构型模式) (Level 300)

    适配器模式的核心概念包括三个主要角色: 1. 目标(Target)接口:这是新系统期望的接口,客户端直接与目标接口交互。 2. 适配器(Adapter)类:适配器是模式的核心,它实现了目标接口,并通过内部持有旧的组件或者...

    适配器模式_famouss4m_适配器模式_源码

    适配器模式的核心概念包括三部分:目标(Target)、适配者(Adaptee)和适配器(Adapter)。目标是客户端期望调用的接口,适配者是需要被适配的对象,而适配器则是连接目标和适配者的桥梁,它实现了目标接口,并通过...

Global site tag (gtag.js) - Google Analytics