前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >适配器模式浅析

适配器模式浅析

作者头像
孟君
发布2019-09-10 15:22:15
4460
发布2019-09-10 15:22:15
举报
文章被收录于专栏:孟君的编程札记

在开始本文之前,我们先来看下生活中的一些场景,比如有些插头需要三口插座转两口插座。

又如美国的电压是110v,而中国的电压是220v。如果要在中国使用美国的电器,需要有一个将电压从220v转化成110v的变压器才可以适配。这样的场景就是今天要讲的适配器(Adapter)模式所做的事。

一、适配器模式的基本介绍

1.1 意图

适配器模式是一种类对象结构性模式,其意图是将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能再一起工作的那些类可以一起工作。

1.2 结构

代码语言:javascript
复制
适配器模式包括2种形式,
  1、类适配
  2、对象适配
  • 类适配器模式
  • 对象适配器模式

主要包含如下几个部分:

  • Target

定义Client使用的与特定领域相关的接口。

  • Adaptee

定义一个已经存在的接口,这个接口需要适配。

  • Adapter

对Adaptee的接口和与Target接口进行适配。

二、类适配示例

类适配采用继承的方式实现

  • OldFunction - Adaptee
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.adapter;

public class OldFunction {

  public void handleRequest() {
    System.out.println("OldFunction - handle request~~");
  }
}
  • Target - Target
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.adapter;

public interface Target {

  void request();
}
  • ClassAdapter - Adapter
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.adapter;

public class ClassAdapter extends OldFunction implements Target {

  public void request() {
    /**
       * 直接调用OldFunction的handleRequest方法即可
     */
    super.handleRequest();
    
  }

  
}

测试一下

代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.adapter;

public class ClassAdapterMain {

  public static void main(String[] args) {
    Target target = new ClassAdapter();
    //OldFunction - handle request~~
    target.request();
  }
}

输出

代码语言:javascript
复制
OldFunction - handle request~~

那么问题来了 - 如果适配器已经有继承,如何使用原来的功能呢?答案是可以使用对象适配来完成。

三、对象适配示例

对象适配采用的是委派的方式实现

  • OldFunction - Adaptee
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.adapter;

public class OldFunction {

  public void handleRequest() {
    System.out.println("OldFunction - handle request~~");
  }
}
  • Target - Target
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.adapter;

public interface Target {

  void request();
}
  • ObjectAdapter - Adapter
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.adapter;

public class ObjectAdapter implements Target {
  private OldFunction oldFunction;

  public ObjectAdapter(OldFunction oldFunction) {
    this.oldFunction = oldFunction;
  }

  public void request() {
    /**
     * 委派调用OldFunction的handleRequest方法
     */
    oldFunction.handleRequest();
    
  }
  
}

测试一下

代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.adapter;

public class ObjectAdapterMain {

  public static void main(String[] args) {
    
    OldFunction adaptee = new OldFunction();
    Target target = new ObjectAdapter(adaptee);
    //OldFunction - handle request~~
    target.request();
  }
}

输出

代码语言:javascript
复制
OldFunction - handle request~~

四、小结

4.1 类适配 vs. 对象适配

类适配器和对象适配有不同的权衡。类适配器

  • 使得Adapter可以重新定义Adaptee的部分行为,因为Adapter是Adaptee的一个子类。
  • 仅仅引入了一个对象,并不需要额外的指针以间接得到adaptee。

对象适配器则:

  • 允许一个Adapter与多个Adaptee同时工作。

4.2 适合适配器使用的场景

  • 系统需要使用的类,而此类的接口不符合系统的需要。
  • 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。这些源类不一定有很复杂的接口。
  • 对对象的适配器模式而言,在设计里,需要改变多个已有的子类的接口,如果使用类的适配器模式,就要针对每一个子类做一个适配器类,而这不太实际。

4.3 JDK中的适配器模式例子

JDK提供了多个适配器模式的例子,如

  • java.util.Arrays#asList()
  • java.util.Collections#list()
  • java.util.Collections#enumeration()
  • java.io.InputStreamReader(InputStream) (returns a Reader)
  • java.io.OutputStreamWriter(OutputStream) (returns a Writer)
  • java.util.collections#enumeration(),从Iterator到Enumeration的适配。
代码语言:javascript
复制

    /**
     * Returns an enumeration over the specified collection.  This provides
     * interoperability with legacy APIs that require an enumeration
     * as input.
     *
     * <p>The iterator returned from a call to {@link Enumeration#asIterator()}
     * does not support removal of elements from the specified collection.  This
     * is necessary to avoid unintentionally increasing the capabilities of the
     * returned enumeration.
     *
     * @param  <T> the class of the objects in the collection
     * @param c the collection for which an enumeration is to be returned.
     * @return an enumeration over the specified collection.
     * @see Enumeration
     */
    public static <T> Enumeration<T> enumeration(final Collection<T> c) {
        return new Enumeration<T>() {
            private final Iterator<T> i = c.iterator();

            public boolean hasMoreElements() {
                return i.hasNext();
            }

            public T nextElement() {
                return i.next();
            }
        };
    }
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档