• 设计模式之适配器模式


    1 概述

      适配器模式(Adapter),说白了就是为了挂羊头卖狗肉而专门设计的模式。也就是把一个类的接口变换成客户端所期待的另一种接口。

      适配器模式通过定义一个新的接口(对要实现的功能加以抽象),和一个实现该接口的Adapter(适配器)类来透明地调用外部组件。这样替换外部组件时,最多只要修改几个Adapter类就可以了,其他源代码都不会受到影响。

         还是以手机为例子,每一种机型都自带有从电器,有一天自带充电器坏了,而且市场没有这类型充电器可买了,怎么办?万能充电器就可以解决,这个万能充电器就是适配器。

         适配器模式有两种形式,一种是类的适配,另一种自然就是对象的适配。

    1.1 类的适配

        这种适配方式,由以下几个角色组成:

    (1)目标(Target)角色:这就是所期待得到的接口。注意:由于这里讨论的是类适配器模式,因此目标不可以是类。

    (2)源(Adapee)角色:现在需要适配的接口。

    (3)适配器(Adaper)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。

    1.2 对象的适配

      对象的适配依赖于对象的组合,而不是类适配中的继承。

         直接上例子来说明更容易理解。

    2 示例

        首先来一个IPhone的充电器类(Adaptee角色):

     1 package org.scott.adapter;
     2 /** 
     3  * @author Scott
     4  * @date 2013-11-23 
     5  * @description
     6  */
     7 public class IPhoneCharger {
     8     public void applePhoneCharge(){
     9         System.out.println("The iPhone is charging ...");
    10     }
    11 }

    现在,要对这个特殊的充电器进行适配,上个适配的接口(Target角色)

    1 package org.scott.adapter;
    2 /** 
    3  * @author Scott
    4  * @date 2013-11-23 
    5  * @description
    6  */
    7 public interface ChargeAdapter {
    8     public void phoneCharge();
    9 }

    因为适配有两种,所以先进行类的适配示例,创建类的适配器

     1 package org.scott.adapterclass;
     2 
     3 import org.scott.adapter.ChargeAdapter;
     4 import org.scott.adapter.IPhoneCharger;
     5 
     6 /** 
     7  * @author Scott
     8  * @date 2013-11-23 
     9  * @description
    10  */
    11 public class UniversalCharger extends IPhoneCharger implements ChargeAdapter{
    12 
    13     @Override
    14     public void phoneCharge() {
    15         System.out.println("The phone is charging, but which kind of phone it is, who cares ...");
    16         
    17         //iphone charging
    18         super.applePhoneCharge();
    19     }
    20     
    21 }

    这就是万能充电器了,我们让它来充个电,测试类准备:

     1 package org.scott.adapterclass;
     2 
     3 import org.scott.adapter.ChargeAdapter;
     4 
     5 /** 
     6  * @author Scott
     7  * @date 2013-11-23 
     8  * @description
     9  */
    10 public class AdapterClassTest {
    11 
    12     public static void main(String[] args) {
    13         ChargeAdapter charger = new UniversalCharger();
    14         charger.phoneCharge();
    15     }
    16 
    17 }

    充电结果:

    The phone is charging, but which kind of phone it is, who cares ...
    The iPhone is charging ...

    ok,以上是类的适配,我们还有种对象的适配方式,创建对象的适配器

     1 package org.scott.adapterobject;
     2 
     3 import org.scott.adapter.ChargeAdapter;
     4 import org.scott.adapter.IPhoneCharger;
     5 
     6 /** 
     7  * @author Scott
     8  * @date 2013-11-23 
     9  * @description
    10  */
    11 public class UniversalCharger implements ChargeAdapter{
    12     IPhoneCharger iphoneCharger;
    13     
    14     public UniversalCharger(IPhoneCharger iphoneCharger){
    15         this.iphoneCharger = iphoneCharger;
    16     }
    17     
    18     @Override
    19     public void phoneCharge() {
    20         System.out.println("The phone is charging, but which kind of phone it is, who cares ...");
    21         iphoneCharger.applePhoneCharge();    
    22     }
    23 
    24 
    25 }

    新一代对象适配器创建完毕,测一把:

     1 package org.scott.adapterobject;
     2 
     3 import org.scott.adapter.ChargeAdapter;
     4 import org.scott.adapter.IPhoneCharger;
     5 
     6 /** 
     7  * @author Scott
     8  * @date 2013-11-23 
     9  * @description
    10  */
    11 public class AdapterObjectTest {
    12 
    13     public static void main(String[] args) {
    14         IPhoneCharger iphoneCharger = new IPhoneCharger();
    15         ChargeAdapter charger = new UniversalCharger(iphoneCharger);
    16         charger.phoneCharge();
    17     }
    18 
    19 }

    运行结果:

    The phone is charging, but which kind of phone it is, who cares ...
    The iPhone is charging ...

    ok,目的也达到了。

      小节一下。

    (1)类的适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。

    (2)对象的适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个包装类,持有原类的一个实例,在包装类的方法中,调用实例的方法就行。

      自然,最后还是要来个UML图(源自网络):

    类适配:

    对象适配:

  • 相关阅读:
    [Typescript] 26. Medium Trim
    [Typescript] 24. Medium Type Lookup
    [Typescript] 23. Medium Promise.all
    AcWing 368. 银河
    无向图的双连通分量
    P1656 炸铁路
    T103489 【模板】边双连通分量
    AcWing 1183 电力
    T103492 【模板】点双连通分量
    AcWing 257. 关押罪犯
  • 原文地址:https://www.cnblogs.com/Scott007/p/3439576.html
Copyright © 2020-2023  润新知