适配器模式(Adapter模式)详解

2021-06-11  本文已影响0人  wuchao226

模式的定义

适配器模式(Adapter)将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

适配器模式分为类适配器模式对象适配器模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。

模式的结构与实现

类适配器模式采用多重继承对一个接口与另外一个接口进行匹配,Java 不支持多继承,但可以定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。

对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口。

现在来介绍它们的基本结构。

1. 模式的结构与特点

适配器模式(Adapter)包含以下主要角色。

优点:

缺点:

类适配器模式的结构图:

类适配器模式的结构图

对象适配器模式的结构图:

对象适配器模式的结构图

2. 模式的实现

类适配器模式的代码如下:

/**
 * 这是客户所期待的接口,目标可以是具体的或抽象类,也可以是接口
 */
public interface Target {
    void request();
}

/**
 * 需要适配的类,被访问和适配的现存组件库中的组件接口
 */
public class Adaptee {
    public void specificRequest(){
        System.out.println("适配者中的业务代码被调用!");
    }
}

/**
 * 类适配器类
 */
public class ClassAdapter extends Adaptee implements Target{
    @Override
    public void request() {
        specificRequest();
    }
}

//客户端代码
public class ClassAdapterTest
{
    public static void main(String[] args)
    {
        System.out.println("类适配器模式测试:");
        Target target = new ClassAdapter();
        target.request();
    }
}

运行结果如下:

类适配器模式测试:
适配者中的业务代码被调用!

对象适配器模式的代码如下:

/**
 * 对象适配器,通过在内部包装一个 Adaptee 对象,把源接口转换为目标接口
 */
public class ObjectAdapter implements Target {

    // 建立一个私有的 Adaptee 对象
    private Adaptee adaptee;

    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void request() {
        // 把表面上调用 request() 方法变成实际调用 specificRequest() 
        adaptee.specificRequest();
    }
}

//客户端代码
public class ObjectAdapterTest
{
    public static void main(String[] args)
    {
        System.out.println("对象适配器模式测试:");
        // 对客户端来说,调用的就是 Target 的 request()
        Target target = new ObjectAdapter();
        target.request();
    }
}

运行结果如下:

类适配器模式测试:
适配者中的业务代码被调用!

适配器模式使用场景

模式的应用实例

用适配器模式(Adapter)模拟火箭队比赛,教练暂停时给后卫、中锋、前锋分配进攻和防守的方法。

适配器结构图

后卫、中锋、前锋都是球员,所有应该有个球员抽象类,有进攻和防守的方法。

/**
 * 抽象球员类
 */
public abstract class Player {

    /**
     * 球员名字
     */
    protected String name;

    public Player(String name) {
        this.name = name;
    }

    /**
     * 进攻方法
     */
    public abstract void attack();

    /**
     * 防守方法
     */
    public abstract void defense();
}


/**
 * 前锋
 */
public class Forwards extends Player {

    public Forwards(String name) {
        super(name);
    }

    @Override
    public void attack() {
        System.out.println("前锋「0」进攻  " + name);
    }

    @Override
    public void defense() {
        System.out.println("前锋「0」防守  " + name);
    }
}

/**
 * 中锋
 */
public class Center extends Player {

    public Center(String name) {
        super(name);
    }

    @Override
    public void attack() {
        System.out.println("中锋「0」进攻  " + name);
    }

    @Override
    public void defense() {
        System.out.println("中锋「0」防守  " + name);
    }
}

/**
 * 后卫
 */
public class Guards extends Player {

    public Guards(String name) {
        super(name);
    }

    @Override
    public void attack() {
        System.out.println("后卫「0」进攻  " + name);
    }

    @Override
    public void defense() {
        System.out.println("后卫「0」防守  " + name);
    }
}
/**
 * 外籍中锋
 */
public class ForeignCenter {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void attackForeign() {
        System.out.println("外籍中锋「0」进攻  " + name);
    }

    public void defenseForeign() {
        System.out.println("外籍中锋「0」防守  " + name);
    }
}


/**
 * 翻译者
 */
public class Translator extends Player {
    // 申明并实例化一个内部"外籍中锋"对象,表明翻译者与外籍球员有关联
    private ForeignCenter foreignCenter = new ForeignCenter();

    public Translator(String name) {
        super(name);
    }

    /**
     * 翻译者将"attack"翻译为"进攻"告诉外籍中锋
     */
    @Override
    public void attack() {
        foreignCenter.attackForeign();
    }

    /**
     * 翻译者将"defense"翻译为"防守"告诉外籍中锋
     */
    @Override
    public void defense() {
        foreignCenter.defenseForeign();
    }
}


public class PlayerTest {
    public static void main(String[] args) {
        Player forwards = new Forwards("巴蒂尔");
        forwards.attack();

        Player center = new Center("科比");
        center.attack();

        Player guards = new Guards("詹姆斯");
        guards.attack();

        // 翻译者
        Translator translator = new Translator("姚明");
        translator.attack();
        translator.defense();
    }
}

运行结果:

前锋「0」进攻  巴蒂尔
中锋「0」进攻  科比
后卫「0」进攻  詹姆斯
外籍中锋「0」进攻  姚明
外籍中锋「0」防守  姚明
上一篇 下一篇

猜你喜欢

热点阅读