跳至主要內容

[设计模式]-结构型-适配器模式

holic-x...大约 5 分钟设计模式设计模式

[设计模式]-结构型-适配器模式

基本概念

概念说明

​ 适配器模式的主要作⽤就是把原本不兼容的接⼝,通过适配修改做到统⼀。使得⽤户⽅便使⽤,就像我们提到的万能充、数据线、MAC笔记本的转换头、出国旅游买个插座等等,他们都是为了适配各种不同的口做的兼容

​ 在业务开发中我们会经常的需要做不同接⼝的兼容,尤其是中台服务,中台需要把各个业务线的各种类型服务做统⼀包装,再对外提供接⼝进⾏使⽤。⽽这在我们平常的开发中也是⾮常常⻅的。

场景案例分析

​ 类似数据源接入场景

场景分析

​ 概念说明:本场景中使用适配器模式,通过转换,让两个系统能够完成对接。例如要调用一个对方接口,但是对方接口提供的调用参数和自身项目预期的参数不一致,因此借助适配器模式进行转化,可以和现实场景的转换器对照。

为什么要定制统一的规范,可以适当避免一些盲目接入接口的场景

定制统一的数据源接入规范(标准) :

  • 什么数据源允许接入?

  • 数据源接入时要满足什么要求?

  • 需要接入方注意什么事情?

本系统要求:任何接入我们系统的数据,它必须要能够根据关键词搜索、并且支持分页搜索。通过声明接口的方式来定义规范。

❓问题扩展:假如说数据源已经支持了搜索,但是原有的方法参数和规范不一致,怎么办?

例如此处提供了Picture、User、Post等多个数据源,但其中Post是接入本地数据库进行查找,需要对请求信息进行校验 ,但这个request又不是各个数据搜索所必须的条件,遇到这种情况如何去做相应处理

【1】最直接了断的方式:不满足规范考虑剔除,对接参数需求额外提供接口/方法进行处理

【2】想办法解决参数问题:尽量自主获取到参数信息,此处借助RequestContextHolder获取请求信息从而拿到所需数据,但也会引申一个问题:当请求来源不同的时候这个request可能和系统所需的有所出入(或者如果借助shiro等一些权限校验框架,可以考虑通过其提供的工具类获取)

【3】有待考究的方式:修改规范,确认其他接口是否也是需要这个参数,但这个改造成本可能在后期会显得大,因为一些现有的接口已经按照既定规范执行,唯恐牵一发动全身

上述方式都是基于不同场景的考虑,需要结合实际选择一种改动最优的方式去解决,由于一开始就统一了规范,要规避一些已经上线结构因规范调整而牵动的联动

适配器模式:

​ 针对不同数据源接入。定义DataSource接口和search接口方法(约定查找参数和返回结果),不同的数据源接入可通过实现DataSource接口方法完成不同的检索操作

// 1.定义DataSource接口统一规范,提供方法入口:统一入参和出参
public interface DataSource<T> {
    /**
     * 搜索(确定入参、出参):例如此处根据查找类型
     */
    void doSearch(String searchText);
}

// 2.多个不同DataSource实现
public class XXXDataSource implements DataSource<Picture> {
    @Override
    public void doSearch(String searchText) {
        return null;
    }
}

// 3.项目中应用:获取到指定数据源,随后调用对应的doSearch方法
DataSource dataSource = new XXXDataSource();
dataSource.doSearch("xxxx");

设计实现

实现:定义DataSource接口统一接口方法规范,不同数据源接入PictureDataSource、UserDataSource、PostDataSource实现接口实现对应业务逻辑封装。如果说要接入新的数据源,则定义xxxDataSource去实现相应的接口方法

// 1.定义DataSource接口统一规范,提供方法入口:统一入参和出参
// 入参:查询条件、出参:分页数据(为了便于前后端统一分页数据统一为dataList)
public interface DataSource<T> {

    /**
     * 搜索
     */
    Page<T> doSearch(String searchText, long pageNum, long pageSize);
}

// 2.多个不同DataSource实现
public class PictureDataSource implements DataSource<Picture> {
    @Override
    public Page<Picture> doSearch(String searchText, long pageNum, long pageSize) {
        return null;
    }
}

public class UserDataSource implements DataSource<User> {
    @Override
    public Page<User> doSearch(String searchText, long pageNum, long pageSize) {
        return null;
    }
}

public class PostDataSource implements DataSource<Post> {
    @Override
    public Page<Post> doSearch(String searchText, long pageNum, long pageSize) {
        return null;
    }
}

// 3.响应交互:对外提供接口,根据入参确认访问的数据库(伪代码参考)
public BaseResponse<SearchVO> searchAllByCondAdaptor(@RequestBody SearchRequest searchRequest, HttpServletRequest request) {
    // a.参数校验
    // b.根据不同数据源进行接入
    // c.封装响应数据并返回
     ----------------------------------------数据源接入参考----------------------------------------------------------------
            DataSource dataSource = null;
            // 根据Type类别分别处理
            switch (searchTypeEnum){
                case PICTURE:
                    // 指定图片数据源
                    dataSource = pictureDataSource;
                    break;
                case USER:
                    // 指定用户数据源
                    dataSource = userDataSource;
                    break;
                case POST:
                    // 指定文章数据源
                    dataSource = postDataSource;
                    break;
                default:
            }
            // 根据数据源调用适配器方法获取相应的分页数据
            Page page = dataSource.doSearch(searchText, searchRequest.getCurrent(), searchRequest.getPageSize());
            // 最终将查询到的数据信息进行封装并返回
          return 封装后的响应数据;
  ----------------------------------------------------------------------------------------------------------------
    }
}

// 4.业务扩展:需要接入新的数据源(例如此处需要接入视频数据源,则只需要实现相应的DataSource规范的接口)
-- a.接入新数据源
public class VideoDataSource implements DataSource<Object> {
    @Override
    public Page<Object> doSearch(String searchText, long pageNum, long pageSize) {
        return null;
    }
}
-- b.业务逻辑引申处理
// 参考步骤3中controller层处理,只需要在条件语句中补充新接入的数据源即可
          switch (searchTypeEnum){
                case PICTURE:
                    // 指定图片数据源
                    dataSource = pictureDataSource;
                    break;
                case VIDEO:
                    // 新接入视频数据源
                    dataSource = videoDataSource;
                    break;
                case MORE:
                    // 更多数据源接入
                    dataSource = moreDataSource;
                    break;
                default:
            }
            // 根据数据源调用适配器方法获取相应的分页数据
            Page page = dataSource.doSearch(searchText, searchRequest.getCurrent(), searchRequest.getPageSize());
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.1.3