适配器模式

适配器模式

       适配器模式是把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法一起工作的两个类能够在一起工作。

 

1.1类的适配器模式

       类的适配器模式把被适配的类的API转换为目标类的API,其静态结构图下:

 

 

类的适配器模式由目标角色、源角色、适配器角色组成。

       目标(Target)角色:客户端所期待的接口。

       源(Adaptee)角色:现有需要适配的类。

       适配器(Adapter)角色:把源接口转换成目标接口,这里适配器角色必须是具体类。

 

目标角色:

/**
 * 目标角色
 */
public interface Target {

    /**
     * 源也有的方法
     */
    void operate1();

    /**
     * 源没有的方法
     */
    void operate2();
}

 

源角色: 

/**
 * 源角色
 */
public class Adaptee {
    public void operate1(){
        System.out.println("源角色的方法 ...");
    }
}


适配器角色: 

/**
 * 适配器角色
 */
public class Adapter extends Adaptee implements Target{
    /**
     * 源角色是没有这个方法的,所以需要适配器类补充这个方法
     */
    @Override
    public void operate2() {
        System.out.println("适配器适配源没有的方法 ...");
    }
}


客户端: 

/**
 * 客户端
 */
public class Client {
    public static void main(String[] args) { 
        Target target = new Adapter();
        target.operate1();
        target.operate2();
    }
}

       客户端希望会用Target接口,但此时我们只有一个Adaptee,且Adaptee所实现的功能就是Target所需要的功能。 

       类的适配器模式就是通过创建一个适配器类,并继承源对象和实现目标对象接口。使客户端所期待的Target与现有的类Adaptee关联起来。

 

1.2对象的适配器模式

       类的适配器模式通过继承将目标角色与源角色连接起来。对象的适配器模式则通过委派来关联目标角色和源角色。结构如下:

 

 

目标角色:

/**
 * 目标角色
 */
public interface Target {
    /**
     * 源也有的方法
     */
    void operate1();
    /**
     * 源没有的方法
     */
    void operate2();
}


源角色: 

/**
 * 源角色
 */
public class Adaptee {
    public void operate1(){
        System.out.println("源角色的方法 ...");
    }
}


适配器角色: 

/**
 * 适配器角色
 */
public class Adapter implements Target {
    /**
     * 源角色
     */
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {

        this.adaptee = adaptee;

    }
  
    /**
     * 源角色有的方法,直接委派给源角色调用
     */
    @Override
    public void operate1() {
        adaptee.operate1();
    }

    /**
     * 源角色是没有这个方法的,所以需要适配器类补充这个方法
     */
    @Override
    public void operate2() {
        System.out.println("适配器适配源没有的方法 ...");
    }
}

 

客户端: 

/**
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        Target target = new Adapter(new Adaptee());
        target.operate1();
        target.operate2();
    }
}

       对象的的适配器模式可以把源类及其子类进行适配。同时,由于对象适配器模式是使用委派关联目标角色与源角色,所以目标角色的方法名可以与源角色的方法名不一致,即当目标角色的方法签名改动时,源角色无需修改,只需要更改适配器角色的方法名即可。而类的适配器模式则需要派生出一个源角色的子类对象,并在内部进行新方法的处理。然后是适配器再去适配这个派生类,麻烦很多。 

 

1.3缺省适配器模式

       缺省适配器模式为一个接口提供缺省实现,使子类从这个缺省实现进行扩展而不从原有接口扩展。

 

目标角色:

/**
 * 目标角色
 */
public interface Target {
    void operate1(); 
    void operate2();
}


缺省适配器: 

/**
 * 缺省适配器
 */
public abstract class DefaultAdapter implements Target {
    @Override
    public void operate1() {
    }

    @Override
    public void operate2() {
    }
}


适配器1: 

/**
 * 适配器角色1
 */
public class AdapterOne extends DefaultAdapter {
    @Override
    public void operate1() {
        System.out.println("adapter one ...");
    }
}


适配器2: 

/**
 * 适配器角色2
 */
public class AdapterTwo extends DefaultAdapter{
    @Override
    public void operate2() {
        System.out.println("adapter two  ...");
    }
}


客户端: 

/**
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        Target target1 = new AdapterOne();
        Target target2 = new AdapterTwo();
 
        target1.operate1();
        target1.operate2();
        target2.operate1();
        target2.operate2();
    }
}


       缺省适配器缺省的其实是目标角色接口。假设目标角色接口有很多的方法,当我们实现这个接口时,必须要实现所有的接口方法,但是这些接口方法我可能只会用到其中的一两个。所以需要一个默认的类去实现这个接口的所有方法,这个任务就交给了缺省适配器类。然后我们在根据这个缺省适配器类去派生出子类,然后选择性的重写方法。 

       缺省适配器类必须是抽象类,因为这个类不能被实例化。

 

 

 

 

参考:

《Java与模式》

posted @ 2018-11-04 18:25  Simple°  阅读(185)  评论(0编辑  收藏  举报