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


    介绍

    适配器(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种模式的一个成员,也是还了过去的技术债。

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

  • 相关阅读:
    vue , debounce 使用
    git 合并代码
    vue-snippet-模板
    旋转字符串
    给一个整数数组,找到两个数使得他们的和等于一个给定的数 target。
    水仙花数[js]
    一道笔试题(vue,react)
    OC中一些基本概念
    如何添加渐变?
    UIBarButtonItem关于全局修改,局部修改
  • 原文地址:https://www.cnblogs.com/liushijie/p/4712894.html
Copyright © 2020-2023  润新知