设计模式学习笔记十四:适配器模式

介绍

适配器(ADPATER)模式,也叫包装器(WRAPPER)模式,属于类对象结构型模式。是为了在现有功能类的基础上为客户提供匹配的接口。适配器有两种方式:对象适配器模式和类适配器模式,本文主要讲前者,后者会有单独的说明,因为个人不是很喜欢这种方式的调用。

意图:将一个类的接口转换成客户希望的另外一个接口。 Adapter模式使得原本由于接口不兼容
而不能一起工作的那些类可以一起工作(本段摘自《GoF设计模式》 4.1)。

适配器模式有几个要素:

  • 目标接口:客户直接掉用的接口;
  • 原始功能类:即被适配者,可以被复用的工具箱;
  • 适配器:实现目标接口,引入原始功能类;

应用

  • 电源适配器
  • 高清转换头
  • spring-mybatis

适用场景

现有功能大部分都能够被新的需求复用。

UML结构图:

Adapter

场景模拟

我是一家旅游网站,从事酒店出售业务。为了提高销售业绩,公司要把产品放到去哪儿网上出售,希望技术部门能实现对接。首先自营网站是有预定产品的所有相关实现的,那么开发人员要做的事情写更少、更优雅的代码完成任务。适配器就适合在这样的场景。

代码实现:

1.定义目标接口

/**
 * 客户调用的目标接口
 */
public interface HotelTarget {
    /**
     * 还有没有房间
     */
    boolean checkQuota(Integer roomId);

    /**
     * 预定房间
     * @return
     */
    boolean bookRoom(Integer roomId);
}

2.酒店适配器

/**
 * 酒店适配器
 */
public class HotelAdapter implements HotelTarget {
    private HotelBiz hotelBiz;
    public HotelAdapter(HotelBiz hotelBiz) {
        this.hotelBiz = hotelBiz;
    }
    /**
     * 还有没有房间
     */
    @Override
    public boolean checkQuota(Integer roomId) {
        return hotelBiz.getQuota(roomId) > 0;
    }

    /**
     * 预定房间
     *
     * @return
     */
    @Override
    public boolean bookRoom(Integer roomId) {
        return hotelBiz.bookRoom(roomId);
    }
}

3.被适配者

/**
 * 酒店业务逻辑类
 */
public class HotelBiz {
    /**
     * 剩余房间数
     * @param roomId
     * @return
     */
    public int getQuota(Integer roomId) {
        int quota = 1;
        System.out.println("房间ID为" + roomId + "的配额 " + quota);
        return quota;
    }

    /**
     * 下订单
     * @param roomId
     * @return
     */
    public boolean bookRoom(Integer roomId) {
        System.out.println("房间ID是" + roomId + "的订单预定成功,入住日期:2015-07-28,离店日期:2015-08-01");
        return true;
    }
}

4.调用者

/**
 * 目标客户
 */
public class Client {
    public static void main(String[] args) {
        HotelBiz hotelBiz = new HotelBiz();
        HotelTarget target = new HotelAdapter(hotelBiz);
        Integer roomId = 1234;
        boolean hasRoom = target.checkQuota(roomId);
        if (hasRoom) {
            target.bookRoom(roomId);
        }
    }
}

5.输出

房间ID为1234的配额 1
房间ID是1234的订单预定成功,入住日期:2015-07-28,离店日期:2015-08-01

另一种实现方式

其实我们也可以直接继承HotelBiz类,这样同样也可以实现,并且代码量会少很多,这个模式就是类适配器模式。乍看来会比较简单,看事情复杂度不能完全以demo为例,demo只是为了达到表达目的对现实抽象到不能再抽象的实现而已,一个系统中不是一个类在工作。同时java中是不支持多继承的,想象一下如果要想达到继承多个类的效果会有多么的麻烦。受累、被鄙视都不是一个程序员希望的。

最后的告白

上述实现就是适配器的全部了,应该是很好理解。相信很多人在写代码时候都这么写过,只是有的人不知道这个玩意的“术语”而已。对,我也写过。写到最后发现这篇文章存在的价值是作为常见23种模式的一个成员,也是还了过去的技术债。

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2015-07-28 02:08  土豆条  阅读(186)  评论(0编辑  收藏  举报