设计模式08_适配器模式

本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/51570748


1、定义

适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器让原本不兼容的类可以合作无间。(摘自Head First中文版243页)


2、说明

通常情况下的适配器模式有两种形式:对象适配器和类适配器。类的适配器模式采用继承实现,而对象适配器采用对象组合方式实现。

类适配器使用继承的方式(静态方式),这样就使得适配器不能和Adaptee的子类一起工作。当目标类数量随着业务需求变得越来越多时,会使得代码结构变得复杂,以至于难以维护;对象适配器使用对象组合的方式(动态组合方式),一个适配器可以把多种不同的源适配到同一个目标,即同一个适配器可以把源类和源类的子类都适配到目标接口。所以在实际情况下,建议尽量多使用对象适配器的实现方式,即多用组合、少用继承。但是对于具体的问题,还是需要选择合适的方式去实现。

那什么时候使用适配器模式呢?一种情况是,你想使用一个已经存在的类,而其接口不符合你的需求。你打算创建一个可以复用的类,该类可以与其它不相关的类或不可预见的类(即接口间不兼容的类)协同工作,则可以考虑使用适配器模式。另一种情况是,你想使用一些已经存在的类,但是不可能对每一个类都子类化以匹配它们的接口,这时可以考虑使用(对象)适配器模式(对象适配器可以适配它的父类接口)。


3、角色

目标接口(Target):客户所期待的接口,具体类、抽象类、接口。

待适配的类(Adaptee):需要适配的类。

适配器(Adapter):包装一个需要适配的对象,把原接口转换成目标接口。 


4、类图


5、示例

类适配器示例如下所示:

package headfirst.design.adapter.extend;

/**
 * 已存在的、具有特殊功能、但不符合我们既有的标准接口的类
 */
public class Adaptee {
    public void specialMethod() {
        System.err.println("这是一个经过适配的特殊的方法");
    }
}
package headfirst.design.adapter.extend;

/**
 * 定义客户端期待的接口
 */
public interface Itarget {
    public void method();
}
package headfirst.design.adapter.extend;

/**
 *适配器,表面上调用method()方法,实际调用specialMethod()
 */
public class Adapter extends Adaptee implements Itarget{
    @Override
    public void method() {
        super.specialMethod();
    }
}
package headfirst.design.adapter.extend;

public class Test {
    public static void main(String[] args) {
        Itarget adapter = new Adapter();
        adapter.method();
    }
}


对象适配器示例如下所示:

package headfirst.design.adapter;

/**
 * 男人相关接口
 */
public interface IMen {

    public void run();

    public void sleep();

    public void groupBaby();
}
package headfirst.design.adapter;

/**
 * 具体类
 */
public class Men implements IMen {

    @Override
    public void run() {

        System.err.println("Men run fast");
    }

    @Override
    public void sleep() {
        System.err.println("Men want sleep");

    }

    @Override
    public void groupBaby() {
        System.err.println("men can group baby");
    }

}
package headfirst.design.adapter;

/**
 * 女人相关接口
 *
 */
public interface IWomen {
    public void womenrun();

    public void womensleep();

    public void womencreatBaby();
}
package headfirst.design.adapter;

/**
 * 具体类
 * @author liqqc
 *
 */
public class Women implements IWomen {

    @Override
    public void womenrun() {
        System.err.println("women run slow");

    }

    @Override
    public void womensleep() {

        System.err.println("women need to sleep");
    }

    @Override
    public void womencreatBaby() {
        System.err.println("women can create baby");

    }

}
package headfirst.design.adapter;

/**
 * 将男人进行适配
 *
 */
public class Adapter implements IWomen {
    private IMen men;

    public Adapter(IMen men) {
        super();
        this.men = men;
    }

    @Override
    public void womenrun() {
        men.run();
    }

    @Override
    public void womensleep() {
        men.sleep();
    }

    @Override
    public void womencreatBaby() {
        men.groupBaby();
    }

}
package headfirst.design.adapter;

public class Test {
    public static void main(String[] args) {

        Men men = new Men(); //创建一个男人
        Women women = new Women(); //创建一个女人
        IWomen awomen = new Adapter(men);//将男人包装到一个女人适配器,让他看起来像女人
        awomen.womenrun();
        awomen.womensleep();
        awomen.womencreatBaby();

        System.err.println("women....");
        women.womenrun();
        women.womensleep();
        women.womencreatBaby();
    }
}
Console:
Men run fast
Men want sleep
men can group baby
women....
women run slow
women need to sleep
women can create baby

6、总结

Java IO 中主要使用了两种设计模式:装饰者模式和适配器模式。在前面的一篇文章中已阐述了装饰者模式。这里将简单阐述下Java IO中的适配模式。查看IO源码可以发现:

public class InputStreamReader extends Reader {

    private final StreamDecoder sd;

    /**
     * Creates an InputStreamReader that uses the default charset.
     *
     * @param  in   An InputStream
     */
    public InputStreamReader(InputStream in) {
        super(in);
        try {
            sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
        } catch (UnsupportedEncodingException e) {
            // The default encoding should always be available
            throw new Error(e);
        }
    }

InputStreamReader 的构造方法中传入的是InputStream,说明将InputStream转换成了Reader,而StreamDecoder的设计实现实际上采用了适配器模式。所以我们常说InputStreamReader和OutputStreamWriter做了InputStream/OutputStream字节流类到Reader/Writer之间的转换,即InputStreamReader和OutputStreamWriter是字节流通向字符流的桥梁

适配器模式的优点:复用性好。系统需要使用已有的类,而该类接口不符合系统当前的需要,则可通过适配器模式让这些功能得到更好的复用。扩展性好。在实现适配器功能时,可以依据需求增加功能,进而自然地扩展系统的功能。

适配器模式的缺点:项目中过多的使用适配器,会让系统代码变得零乱,不好整体把握系统。例如,在某个业务中表面上看到调用的是接口A,但其实其内部被适配成了接口B的实现,如果太多出现这种情况,那么系统面临的将是一场灾难。一般情况下,如果不是非常有必要,最好不使用适配器,而是对系统进行相应的重构。

本文只是简单介绍了适配器模式,并未对其进行深入探讨,略显粗糙。希望本文对你有所帮助。


时间: 2024-12-14 11:37:48

设计模式08_适配器模式的相关文章

设计模式之适配器模式

适配器模式(Adapter Pattern)有时候也称包装样式或者包装.将一个类的接口转接成用户所期待的.一个适配使得因接口不兼容而不能在一起工作的类工作在一起,做法是将类别自己的接口包裹在一个已存在的类中. Adapter Pattern有两种: 类的Adapter Pattern(继承) 对象的Adapter Pattern(委托) 下面我们用第一种来实现适配器模式: 我们首先来看看类图: 具体实现如下: Banner类: public class Banner { private Stri

设计模式之适配器模式(Adapter Pattern)

适配器模式(Adapter):将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 1. 解决的问题 即Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 2. 模式中的角色 2.1 目标接口(Target):客户所期待的接口.目标可以是具体的或抽象的类,也可以是接口. 2.2 需要适配的类(Adaptee):需要适配的类或适配者类. 2.3 适配器(Adapter):通过包装一个需要适配的对象,把

大话设计模式_适配器模式(Java代码)

适配器模式:将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 简单描述: 大话设计模式中的截图: 代码例子: AbstractPlayer类: 1 package com.longsheng.adapter; 2 3 public abstract class AbstractPlayer { 4 5 public abstract void attack(); 6 7 public abstract void defenc

螃蟹学PHP设计模式之适配器模式

之前对java的设计模式略有了解,但是螃蟹目前是靠PHP吃饭,所以对于进阶学习php设计模式还是很有必要.螃蟹虽然做开发两年了,但是在老鸟眼中还是菜鸟,为了自己写的代码更容易维护和进行团队协作,所以我要搞定设计模式.希望螃蟹今年能创业成功或找个好工作. 1.适配器模式 螃蟹的理解是你买了港行的iphone手机,发现自家的插座和手机自带的插头不配,怎么办呢,就需要一个转换器(适配器).可能原来系统的类不是你设计的,但是现在你要使用原来的类,发现有问题,但原来的类又不能动,或者不需要动,这样你写一个

Java设计模式之适配器模式(Adapter Pattern)

Adapter Pattern的作用是在不改变功能的前提下转换接口.Adapter分为两类,一类是Object Adapter, 另一类是Class Adapter.由于Class Adapter的实现需要用到多继承,而Java不支持多继承,所以这里只关注Object Adapter. 在JDK1.5之前是没有 java.util.Iterator 接口的,java.util.Enumeration 接口起着 Iterator 的作用.那么如果我们需要维护一些年代比较久远的代码,可能就会面临着没

Head First 设计模式之适配器模式与外观模式

Head First设计模式之适配器模式与外观模式 前言: 之前讲过装饰者模式,将对象包装起来并赋予新的职责,这一章我们也会将对象进行包装,只不过是让它们看起来不像自己而像是别的东西.这样就可以在设计中将类的接口转化为想要的接口,以实现同的接口,此外还将讲述另一个模式,将对象包装起来以简化接口. 1.   适配器简介 1.1 面向对象的适配器 真实世界的适配器比如位于美式插头和欧式插座之间的交流电适配器.面向对象的适配器是什么呢? 面向对象的适配器是将一个接口转化成另一个接口,以符合客户的期望.

每天一个设计模式-3 适配器模式(Adapteer)

每天一个设计模式-3 适配器模式(Adapteer) 1.现实中的情况 旧式电脑的硬盘是串口的,直接与硬盘连接,新硬盘是并口的,显然新硬盘不能直接连在电脑上,于是就有了转接线.好了,今天的学习主题出来了“适配器”. 2.联系编程 有一个电源类,一个旧的硬盘类,还有一个新硬盘类:电源类能直接适配旧硬盘类,但不能和新硬盘适配. 这时,可以添加一个适配器类,这里采用对象引用的方式实现适配器. 3.类图 模式简图: 测试时使用的类图: 4.代码 NewDiskApi: public interface

Java编程思想笔记02:组合与继承、final、策略设计模式与适配器模式、内部类、序列化控制(注意事项)

1.组合和继承之间的选择 组合和继承都允许在新的类中放置子对象,组合是显式的这样做,而继承则是隐式的做. 组合技术通常用于想在新类中使用现有类的功能而非它的接口这种情形.即在新类中嵌入某个对象,让其实现所需要的功能,但新类的用户看到的只是为新类所定义的接口,而非所嵌入对象的接口.为取得此效果,需要在新类中嵌入一个现有类的private对象.但有时,允许类的用户直接访问新类中的组合成分是极具意义的,即将成员对象声明为public.如果成员对象自身都隐藏了具体实现,那么这种做法是安全的.当用户能够了

JAVA学习笔记--策略设计模式与适配器模式

一.策略设计模式 创建一个能够根据所传递对象的不同而具有不同行为的方法被称为策略设计模式:这类方法包含所要执行的算法中固定不变的部分,而"策略"包含变化的部分.策略就是传递进去的参数对象,它包含要执行的代码. 这种设计模式将算法分别独立封装起来,然后将其当做参数传递给方法从而让方法产生不同的行为,不同的算法可以进行替换(就像给方法不同的实参).我们可以知道,在策略设计模式中有三个部分:策略.策略引用.接收策略引用的方法(这是笔者自己根据理解给出的名词,并没有查询有没有这些术语).下面通