适配器(Adapter)模式
本篇主要讲述适配器设计模式。
1日常生活中的适配器
适配器的例子在日常生活中随处可见。
例如:中国的电源电压为220V,而日本的电源电压110V,在国内使用日本原装电器时,就必须有一个电源适配器将220V的电压适配至110V。
新的电脑鼠标一般都是USB接口,而旧的电脑机箱上根本就没有USB接口,而只有一个PS2接口,这时就必须有一个PS2转USB的适配器,将PS2接口适配为USB接口。
一般家庭中电源插座有的是两个孔(两项式)的,也有三个孔(三项式)的。很多时候我们可能更多地使用三个引脚的插头,但是那种两孔的插座就不能满足我们的需求,此时我们一般会买一个拖线板,该拖线板的插头是是两脚插头,这样就可以插入原先的两孔插座,同时拖线板上带有很多两孔、三孔的插座!这样不仅可以扩容,更主要的是将两孔的插座转变为三孔的插座!
图1为一个将220v电源转换为5v电源的适配器,图2为将PS2接头转换为USB接头的适配器。
图 1 电源适配器 图2鼠标适配器哦
设计模式里的适配器模式和日常生活中的适配器的作用是完全一样的。下面请看设计模式中的适配器模式吧!
2 Adapter模式
适配器模式俗称变压器模式,指将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。从功能上讲这些接口不兼容的类一般具有相同或相似的功能。通常我们通过修改该类的接口来解决这种接口不兼容的情形,但是如果我们不愿意为了一个应用而修改各原有的接口,或者我们压根就没有原有对象的源代码那该怎么办呢? 此时Adapter模式就会派上大用场了。
2.1 适配器模式的几个要素
适配器模式所涉及的角色包括:1.源;2.目标;3.适配器;4.客户。
1. 源(Adaptee):已经存在的、需要适配的类。
2. 目标(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
3. 适配器(Adapter):适配器模式的核心类。有两种方式实现Adapter,对象适配器(Object Adapter)和类适配器(Class Adapter)。
4. 客户(Client):
下图是Adapter设计模式中的几个对象:
2.2 Adapter模式的使用场景和意图
“The Adapter Pattern converts the interface of a class into another interface the clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.”
--GOF 《Element of reusable Object-Oriented Software》
上面是GOF在《可复用元素面向对象》这本书中对适配器模式的概括。很经典的一句话。
从上图我们可以看出Adapter模式使用的场景:我们的新系统中有一个客户(Client)需要一个Target的接口,原有的系统中有一个现成的类(Adaptee),该类具有Target接口所需的功能。但是Adaptee类提供的接口却与客户需要的Target接口不同。在这种情况下,我们希望将现有的接口(Adaptee)转化(convert)为客户类期望的接口(Target),这样不仅保证没有修改原有的系统,更主要的是还能保证对现有类的重用。若不进行这样的转化,客户类就不能利用现有类所提供的功能。
因此在客户需要的接口Target和原系统中具有此功能的类Adaptee间必然需要一个“调停者”对象,根据该对象的功能可以确定此“调停者”必须具有以下两个特点:1.实现Target接口;2.重用Adaptee。该“调停者”就是适配器模式的主角――Adapter类。首先他实现了客户需要的Target接口,因此他可以满足客户(Client)的需要,同时它又重用的原有系统的Adaptee类。
在前面我们讲过在Java中有两种方式可以达到重用的目的:1.继承;2.包含。同样在适配器模式中也可以通过这两种方式达到重用Adaptee类的目的。根据重用使用方式的不同一般将适配器模式分为两类:类适配器(Class Adapter)和对象适配器(Object Adapter)。
2.3 类适配器 VS 对象适配器(尽量用对象适配器,多用合成/聚合、少用继承)
要正确地区别这两种适配器的区别,我们还是从一个简单的例子开始吧!我们的系统中有一个具有某个特定功能的类Adaptee,一个客户类Client――他需要一个实现Target接口的对象,和一个Target接口,以下是他们的源码:
-
-
- public class Adaptee{
-
- public void specialRequest(){
-
- System.out.println("Called SpecificRequest() in Adaptee ");
-
- }
-
- }
-
-
-
-
-
- public class Client {
-
- public static void main(String[] args){
-
- Target t = ……
-
- t.request();
-
- }
-
- }
-
-
-
-
-
-
-
- public interface Target{
-
- public void request();
-
- }
根据上一小节的分析我们知道此时需要一个Adapter对象,该对象实现Target接口,同时他又重用现有的Adaptee类。任何有一点点OO(面向对象)知识的人都会想到通过继承可以达到重用的目的。下面是通过继承实现Adaptee类重用的例子:
-
-
- public class Adapter extends Adaptee implements Target{
-
- public void request(){
-
- this.specialRequest();
-
- }
-
- }
简单明了!现在的过程就是:客户调用Target接口的request方法,实际就是调用其父类Adaptee的specialRequest方法。图4为类适配器(Class Adapter)的类图:
这就是大家通常常说的类的适配器!类适配器具有以下的两个特点:1.适配器类(Adapter)实现Target接口;2. 适配器类(Adapter)通过继承来实现对Adaptee类的重用。
下面是一个通过组合关系实现继承的例子,以下是源码:
-
-
- public class Adapter implements Target{
-
- Adaptee adaptee = new Adaptee();
-
- public void request(){
-
- adaptee.specialRequest();
-
- }
-
- }
以上就是通过组合实现对Adaptee类重用的例子。这就是大家通常说的对象的适配器!对象的适配器具有以下的两个特点:1.适配器类(Adapter)实现Target接口;2. 适配器类(Adapter)通过组合来实现对Adaptee类的重用。图5是对象适配器的类图。
对于这两者不同的适配器客户代码其实是完全一样的。以下是客户的代码:
-
-
- public class Client {
-
- public static void main(String[] args){
-
- Target t = new Adapter() ;
-
- t.request();
-
- }
-
- }
2.4 适配器模式的变体
上面谈到的所有适配器都是通过重用Adaptee类从而实现Target接口中的方法。这只是具体层次的重用。是否还存在更高层次的适配器呢!?答案是肯定的!我们不仅可以适配具体的类还可以适配抽象类,甚至适配接口!下面是这种适配的简图:
从上图可以看出:Adapter将Adaptee接口适配为客户Client需要的接口Target,这样在整个系统中所有实现Adaptee接口的类都可以通过Adapter适配为Target对象,从而避免为每一个类都写一个适配器。后面会给大家带来一个JDK中使用此中适配的例子。我们不仅仅可以象上面一样对接口进行适配,也可以对抽象类进行适配!主要是根据系统的需求,确定此时的场景是否适合使用适配器模式!
以上是适配器模式!关于IO的适配在下面的源代码分析中,会阐述byte数组到InputStream的适配。就当作一个适配器的例子吧!其它关于适配器在Java中的应用以及如何将java.sql.ResultSet适配至javax.swing.table.TableModel、将File、DOM树、Thread适配至javax.swing.tree.TreeModel就不在这里详细讲解了
转自:http://miaoxiaodong78.blog.163.com/blog/static/1876513620070123473737/
分享到:
相关推荐
设计模式之 适配器 Adapter C++ 源码 vs2019 工具,设计模式之 适配器 Adapter C++ 源码 vs2019 工具,设计模式之 适配器 Adapter C++ 源码 vs2019 工具,设计模式之 适配器 Adapter C++ 源码 vs2019 工具,设计模式...
标题“设计模式之适配器Adapter”暗示我们将深入探讨适配器模式的核心概念和应用场景。适配器模式通常应用于以下场景: 1. 当系统中存在一个已经存在的类,其接口不符合新需求时,可以使用适配器模式来调整接口,使...
适配器模式是一种软件设计模式,它允许两个不兼容的接口之间进行通信。在Java中,适配器模式被广泛应用于解决系统间的兼容性问题,尤其是当我们需要将一个已有的类库或者对象与我们的系统接口相匹配时。汽车适配器的...
- **适配器(Adapter)**:适配器类实现了目标接口,内部持有一个原始接口的引用或实例,负责将原始接口的调用转换为目标接口的调用。 - **客户端(Client)**:客户端使用目标接口进行操作,对适配器和原始接口一无所知...
适配器模式(Adapter Pattern)是软件设计模式中的一种,其主要目的是解决系统中的接口不兼容问题,使得原本由于接口不匹配而无法一起工作的类能够协同工作。在本文中,我们将深入探讨适配器模式的概念、结构、作用...
适配器模式(Adapter Pattern)是通过创建一个新的对象(适配器),这个对象将原本不兼容的对象接口转换为客户端期望的接口,从而使两者能够协同工作。适配器模式可以分为类适配器和对象适配器两种类型。 1. 类...
适配器模式(Adapter)是软件工程中一种常用的设计模式,它允许两个不兼容的接口之间进行通信。在C++编程中,适配器模式能够帮助我们复用现有的类,或者将第三方库的接口与我们的系统接口进行对接,从而提高代码的可...
"安卓万能适配器Adapter"的概念旨在提供一种通用的解决方案,减少开发者编写重复代码的时间,提高开发效率。这个适配器设计是基于面向对象编程原则,允许我们灵活地将各种数据类型与视图元素进行绑定。 首先,我们...
适配器模式(Adapter Pattern)是一种结构型设计模式,它主要解决的是接口不兼容的问题,使得原本由于接口差异无法一起工作的类能够协同工作。在PHP中,适配器模式通过创建一个包装类(适配器类)来转换不兼容的接口...
- Adapter是Android系统提供的一种设计模式,用于将数据源(如ArrayList)与UI组件(如ListView)进行连接。它允许开发者将数据转换为列表项视图,并负责在用户界面中显示这些数据。 2. **通用适配器的必要性**:...
文件列表中的"adapter"可能包含了适配器模式的Java源代码文件,这些文件通常会包含以上提到的三个角色的定义。例如,可能会有`Target.java`(目标接口),`Adaptee.java`(被适配者类),以及`Adapter.java`(类...
在这个例子中,`PowerAdapter` 通过继承 `Light` 类实现了类适配器模式,这样可以利用继承带来的多态性。同时,适配器也通过内部持有 `Light` 对象实现了对象适配器模式,通过委托调用来实现接口的转换。 测试这些...
2. 适配器(Adapter)类:这是适配器模式的核心,它实现了目标接口,并持有对适配者对象的引用。适配器类负责将适配者的接口转换为目标接口。 3. 适配者(Adaptee)类:这是需要适配的原始接口或类,它的接口与目标...
为了使ListView显示的数据更加丰富多样,我们通常需要自定义适配器(Adapter)。本文将深入探讨如何创建和使用ListView的自定义适配器,以及它的工作原理。 首先,我们要理解适配器在ListView中的角色。适配器是...
适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将一个接口转换为客户端期望的另一个接口。适配器模式常用于解决由于接口不兼容而无法正常工作的类之间的协作问题。 适配器模式的组成 目标接口(Target...
在`DesignMode_Adapter`这个压缩包文件中,可能包含了相关的C++源码示例,演示了如何创建和使用适配器模式。这些源码可能包括了目标接口、原始接口、适配器类的定义以及客户端如何通过适配器进行调用的示例。通过...
3. 适配器(Adapter):实现了目标接口,并持有对适配者的引用,负责将适配者接口转换为客户期望的目标接口。 适配器模式的优点: 1. 增强了类的复用性,可以利用已有的类进行扩展,而不必修改原有代码。 2. 提高了...
适配器模式是一种设计模式,它允许不兼容的类或接口之间进行通信和协作。这种模式的核心在于创建一个适配器类,该类将原始类(Adaptee)的接口转换为客户期望的目标接口(Target)。适配器模式分为基于类的适配器...