Adapter Pattern:把一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
适配器模式很像变压器(Adapter),变压器把一种电压转换成另一种电压。美国的生活电压是110V,中国的生活电是220V,如果把美国的电器放到中国使用,则必须要有一个能把220V的电压转成110V的变压器。同时,适配器模式的做法也很像货物的包装过程:被包装的货物的真实样子被包装所掩盖和修改,因此也有人把这种模式叫做包装(Wrapper)模式。
适配器有两种形式,类的适配器模式和对象的适配器模式。分写来介绍一下。
类的适配器模式
类的适配器模式把被适配的类的API转换成目标类的API,其静态结构图如下所示:
从上图可以看出,Adaptee类并没有needOperation2()方法,而客户端却期待这个方法。这个时候,我们就可以提供一个中间环节,把Adaptee的API和Adapter的API衔接起来,这个中间环节就是类适配器的核心—Adapter类。Adapter与Adaptee是继承关系,这决定了这个模式是类的适配器模式。
模式设计的角色:
a.目标角色(Target):我们希望得到的接口。Java不支持多重继承,所以在类的适配器模式中,目标角色必须是接口。
b.源角色(Adaptee):需要适配的接口。
c.适配器角色(Adapter):本模式的核心,显然,这一角色不可以是接口,必须是具体的类(因为它既要实现Target接口,又要继承Adaptee类,所以只能是具体的类)。
代码实现:
/**
* 目标角色,在类的适配器模式中,只能是接口
* 定义了两个操作:needOperation1(),needOperation2()
*@author cxy
*/
interface Target {
void needOperation1();
void needOperation2();
}
/**
* 源角色:需要被适配的角色,只提供了目标角色接口的一部分功能
* @author cxy
*/
class Adaptee {
public void needOperation1() {
//do some thing;
}
}
/**
* 适配器角色:本模式的核心,把源类转换成目标接口
* 继承自源类,实现目标接口,所以适配器角色必须是具体的类
* @author cxy
*
*/
class Adapter extends Adaptee implements Target {
//直接调用源类的方法,当然也可以很方便的置换源类的方法
public void needOperation1() {
super.needOperation1();
}
//源类没有的方法,因此,适配器类补上这个方法
public void needOperation2() {
//do some thing;
}
}
在类的适配器模式中,使用一个具体的类(Adapter)把源(Adaptee)适配到目标(Target)中,适配器类时源的子类,因此可以在适配器中很容易的置换掉源类的方法,但是这个适配器类只能适配源类,不能适配源类的子类。
对象的适配器模式
与类的适配器模式不同,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用委派关系。对象的适配器模式的静态结构图:
模式所涉及的角色:
a.目标角色(Target):我们希望得到的接口,可以是接口或者是类。
b.源角色(Adaptee):需要适配的接口。
c.适配器角色(Adapter):本模式的核心,这一角色不可以是接口,必须是具体的类,内部保存着对源类的引用。
代码实现:
/**
* 目标角色,在类的适配器模式中,只能是接口
* 定义了两个操作:needOperation1(),needOperation2()
*@author cxy
*/
interface Target {
void needOperation1();
void needOperation2();
}
/**
* 源角色:需要被适配的角色,只提供了目标角色接口的一部分功能
* @author cxy
*/
class Adaptee {
public void needOperation1() {
//do some thing;
}
}
/**
* 适配器角色:本模式的核心,把源类转换成目标接口
* 内部保存源类的引用,提供源类没有方法
* @author cxy
*
*/
class Adapter extends Adaptee implements Target {
private Adaptee adaptee;
public Adapter(Adaptee ada) {
this.adaptee = ada;
}
//直接调用源类的方法,当然也可以很方便的置换源类的方法
public void needOperation1() {
adaptee.needOperation1();
}
//源类没有的方法,因此,适配器类补上这个方法
public void needOperation2() {
//do some thing;
}
}
对象的适配器模式中,适配器角色内部保存着源角色的引用,而不再使用继承,因此:
(1)一个适配器可以把多种不同的源适配到同一目标,可以把源类和它的子类都适配到目标接口;
(2)想置换源类的方法就比较困难了。如果一定要置换,那么只能在源类的子类中置换,再把子类适配到目标接口,实际上源类的子类才是真正的源;
(3)可以方便的添加新的方法,新添加的方法适用于所有的源。
在以下情况下使用适配器模式:
(1)系统需要使用现有的类,而此类的接口不符合系统的需要。
(2)想要创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作。
(3)(仅适用于对象的Adapter模式)在设计里,想使用一些已经存在的子类,这是让适配器角色在内部保存着父类的引用,就可以把所有子类都适配到目标接口中。
==============================================================================================
下面讲一下缺省适配器(Default Adapter),我觉得缺省适配器应该应用更广泛,尤其是在Java中。
我们知道,如果一个类要实现某个接口,那么就要实现这个接口中的所有方法。比如人的行为接口PersonAction有20方法,男人的行为类ManAction需要实现这20个方法,女人的行为类WomanAction也需要实现这20个类。可问题是,男人和女人的很多行为是相同的,比如吃饭,行走,睡觉等等,在这20个方法中,只有打扮dress()方法不同,难道我们要把另外19个方法都实现两遍吗?这个时候缺省适配器模式就要闪亮登场了,缺省适配器模式为一个接口提供默认实现,这样子类型就可以从这个缺省实现进行扩展,而不需要从原有接口进行扩展。把上面的例子用图展现出来:
这样ManAction类和WomanAction类只需要实现dress()方法就行了。附上源代码:
/**
* 需要实现的接口,方法很多
* @author cxy
*/
interface PersonAction {
void sleep();
void eat();
void walk();
//...
void dress();
}
/**
* 缺省适配器的核心—适配器类
* 提供对目标接口的”平庸“实现
* @author cxy
*/
class DefaultAdapter implements PersonAction{
public void sleep() {
System.out.println("晚上睡觉");
}
public void eat() {
System.out.println("按时吃饭");
}
//...
public void walk() {
System.out.println("双脚走路");
}
public void dress() {}
}
/**
*具体实现,扩展自DefaultAdapter类,
*只需要实现自己关心的逻辑
*@author cxy
*/
class ManAction extends DefaultAdapter {
public void dress() {
System.out.println("男人只洗脸");
}
}
/**
*具体实现,扩展自DefaultAdapter类,
*只需要实现自己关心的逻辑
*@author cxy
*/
class WomanAction extends DefaultAdapter {
public void dress() {
System.out.println("洗面奶洗脸");
System.out.println("做面膜");
System.out.println("还要打扮两个小时才能完成");
}
}
这个DefaultAction类就是适配器类,此适配器类实现了PersonAction接口所要求的所有方法,但是此适配器类给出的所有实现都是“平庸”的,这种“平庸化“的适配器模式就叫做缺省适配器模式。关于”平庸“实现,我参考的是《Java与模式》这本书,上面给出的实现是空实现,也就是不做任何事情,这种实现当然可以叫做平庸,但是我觉得”平庸“应该是所有实现该接口的类具有的共性行为,如果没有共性行为,那就可以使用空实现(如果我的这种理解有错误,请指出,我改正)。从DefaulAction类再扩展,就可以实现自己关心的方法了,我是大大的欣赏缺省适配器模式。
分享到:
相关推荐
在Java中,适配器模式扮演着重要的角色,尤其在处理遗留代码或者第三方库集成时,能够有效地解决接口不匹配的问题。本文将深入探讨适配器模式的概念、类型、优点和如何在Java中实现。 一、适配器模式概念 适配器...
今天我们要探讨的是JAVA设计中的两个重要模式:抽象类与适配器模式。 首先,我们来理解一下“抽象”。抽象是面向对象编程的核心概念之一,它帮助我们处理对象的复杂性。在Java中,抽象通常通过抽象类来实现。抽象类...
Java设计模式中的适配器模式(Adapter Pattern)是一种结构型设计模式,它的主要目的是将不兼容的接口转换为用户期望的接口,使原本由于接口不兼容而无法一起工作的类能够协同工作。适配器模式有两种形式:类适配器...
Java动态代理模式与适配器模式是两种在软件设计中常用的设计模式,它们都有各自的优点和应用场景。在Java中,动态代理模式主要依赖于Java的反射API和InvocationHandler接口,而适配器模式则用于解决不同接口之间的...
在"适配器模式.docx"文档中,可能详细介绍了适配器模式的概念、结构、优缺点以及适用场景,并通过具体的Java代码示例展示了如何实现适配器模式。这些示例可能包括类适配器和对象适配器两种形式,展示如何在实际项目...
在这个Java实现中,我们将深入探讨适配器模式的两大类型:类适配器模式和对象适配器模式,并通过具体的代码示例和UML类图来阐述其工作原理。 首先,我们来理解适配器模式的基本概念。适配器模式就像现实生活中的...
在Java中,适配器模式是通过创建一个新的类(适配器类)来实现目标接口,该适配器类将原始类(被适配者)的接口转换为目标接口,使得原本不兼容的类可以协同工作。 适配器模式主要有两种形式:类适配器模式和对象...
在Java中,适配器模式主要分为两种类型:类适配器模式和对象适配器模式。类适配器模式通过继承目标接口和被适配者类来实现,而对象适配器模式则通过包含被适配者对象并实现目标接口来完成适配过程。 1. 类适配器...
### Java开发适配器模式详解 #### 一、适配器模式概述 适配器模式(Adapter Pattern)是一种常用的设计模式,其主要目的是让两个不兼容的接口能够协同工作。通过引入一个适配器,可以将现有类的接口转换成客户端期望...
### Java设计模式之适配器模式详解 #### 引言 在软件开发中,我们经常遇到需要使用已有的类库,但这些类库的接口与我们的需求不匹配的情况。这时,适配器模式(Adapter Pattern)便能派上用场。适配器模式是一种...
### Java设计模式之适配器模式详解 #### 结构型模式概述 在软件工程领域,设计模式被视为一种标准解决方案,用于解决在特定上下文中经常出现的问题。设计模式按其目的和适用场景,大致可分为三种类型:创建型模式...
适配器模式(Adapter Pattern)是其中的一种,它允许两个不兼容的接口之间进行通信,通过创建一个适配器类来将原有接口转换成目标接口,使得原本不能一起工作的类可以协同工作。 适配器模式分为类适配器和对象...
在 Java 开发中,适配器模式(Adapter Pattern)是一种非常有用的结构型设计模式,它可以帮助我们解决接口不兼容的问题,实现不同类之间的无缝集成。本文将详细介绍适配器模式的意图、解释、编程示例、适用场景、...
在Java编程中,适配器模式能够帮助我们复用已有的类,或者解决新旧系统之间的接口不匹配问题,从而提高代码的可重用性和灵活性。 适配器模式主要有两种形式:类适配器模式和对象适配器模式。在类适配器模式中,...
类适配器模式通常适用于Java、C++等支持多继承的语言。 在对象适配器模式中,适配器类不直接继承被适配类,而是持有被适配类的一个实例,并通过这个实例来调用其方法。适配器类实现目标接口,当需要调用被适配类的...
java设计模式【之】适配器模式【源码】【场景:水和容器】 * 适配器模式,类似(亡羊补牢) * 已经存在的类(功能已经开发完成了),与新需求的功能相似,但是略有差异 * 当已经存在的方法无法满足现有需求,需要...
java常用设计模式-适配器模式 适配器模式(Adapter Pattern)是一种结构型设计模式,它允许不兼容的接口之间进行通信。这种模式可以在不修改现有代码的情况下重用现有类,并且可以使不兼容的接口之间进行通信。 ...
2. 结构型模式:适配器模式、装饰器模式、代理模式、桥接模式、组合模式、外观模式、享元模式。这些模式主要处理类和对象之间的关系,提高代码的可扩展性和模块化。 3. 行为型模式:策略模式、模板方法模式、观察者...
在软件设计领域,设计模式是一种经过时间和实践验证的解决方案,用于解决常见的...这个"设计模式之适配器模式与外观模式demo"资源为学习和实践这两种模式提供了宝贵的实例,对于提升编程技能和设计思维具有积极意义。