【Java设计模式05】—— 适配器模式

1 定义

适配器模式:将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。

适配器模式的好处是,客户不必为了应对不同的接口而每次都跟着改变,只需要将接口转换的部分通过适配器封装起来就可以了。

2 类图

【Java设计模式05】—— 适配器模式_第1张图片

  • Client:客户端,接口调用方。
  • Target:目标接口,客户端所期望使用的接口,也是适配器所要适配的接口。
  • Adaptee:被适配者,系统原有的实现。
  • Adapter:适配器,适配器需要将被适配者的接口适配成Target目标接口。

3 分类

3.1 类适配器(不常用)

3.1.1 结构图

【Java设计模式05】—— 适配器模式_第2张图片

类适配器Adapter是通过继承被适配者Adaptee来达到适配的目的。

3.1.2 例子

Target接口:

/**
 * 目标接口
 */
public interface Target {

    /**
     * 适配方法(客户端期望调用的方法)
     */
    void request();
}

Adaptee类:

/**
 * 被适配者
 */
public class Adaptee {

    /**
     * 被适配的方法
     */
    public void specificRequest() {
        System.out.println("被适配者Adaptee的真实方法调用");
    }
}

Adapter类:

/**
 * 适配器
 * 通过继承Adaptee并且实现Target接口,达到适配的目的
 */
public class Adapter extends Adaptee implements Target {

    @Override
    public void request() {
        super.specificRequest();
    }
}

Client类:

/**
 * 客户端
 */
public class Client {

    /**
     * 调用target的方法
     */
    public void doSomething(Target target) {
        target.request();
    }

    public static void main(String[] args) {
        Adapter adapter = new Adapter();
        new Client().doSomething(adapter);
    }
}

3.1.3 缺点

由于Java是单继承语言,某个类适配器只能服务于一个被适配者,不利于程序的扩展;

并且由于是基于继承的方式,被适配者的所有属性和操作都对适配器暴露,也不利于程序的安全和可控;

所以类适配器的方式其实在实际开发中比较少用

3.2 对象适配器

3.2.1 结构图

【Java设计模式05】—— 适配器模式_第3张图片

在对象适配器中,不是通过继承被适配者Adaptee来适配的,而是通过关联Adaptee来适配,AdapteeAdapter的成员变量。

3.2.2 例子

目标接口IGameProps

/**
 * 目标接口:游戏道具
 */
public interface IGameProps {

    /**
     * 适配方法:计算能够购买的道具数量
     */
    void calculate();
}

被适配者Rmb

/**
 * 被适配者:人民币
 */
public class Rmb {

    /**
     * 人民币面值
     */
    private int count;

    public Rmb(int count) {
        this.count = count;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

适配器GameCurrency

/**
 * 适配器:游戏币
 * 通过依赖Rmb并且实现IGameProps接口,达到适配的目的
 */
public class GameCurrency implements IGameProps {

    /**
     * 人民币对象的引用
     */
    private Rmb rmb;

    /**
     * 游戏币面值
     */
    private int count;

    public GameCurrency(Rmb rmb) {
        this.rmb = rmb;
        // 1人民币等于10游戏币
        this.count = rmb.getCount() * 10;
    }

    @Override
    public void calculate() {
        System.out.println("您拥有游戏币: " + this.getCount() +
                ", 可以购买玩具(单价2游戏币): " + this.getCount() / 2 + "个");
    }

    public int getCount() {
        return count;
    }
}

客户端Client

/**
 * 客户端
 */
public class Client {

    public static void main(String[] args) {
        // 充值5人民币
        Rmb rmb = new Rmb(5);
        // 人民币转游戏币并计算能够购买的道具数量
        new GameCurrency(rmb).calculate();
    }
}

3.2.3 优点

正如上面的例子描述的那样,游戏道具只能用游戏币购买,不能用人民币直接购买。所以,必须定义一个“游戏币”适配器类,来适配“人民币”。

当我们要用这个适配器再适配其他类时,只要在适配器中增加其他类对象的引用就行,这比继承有更好的扩展性。

对象适配器的优点:

  1. 适配器模式可以理解成是在原有基础上的封装,不需要对原有程序进行改动,即可实现特定功能。
  2. 对象适配器可以服务于多个源角色,便于程序的扩展。

你可能感兴趣的:(JAVA设计模式)