适用于对项目进行扩展,适配器模式的好处是不修改原有逻辑进行功能扩展,但是随着功能的增加,适配器的适配种类也会增多。
适用场景:在原有账号密码登录的基础上实现第三方登录。
简介
适配器模式,一个用于将一类的接口适配成用户所期待的接口,能够帮助不兼容的接口变得兼容。
实现
适配器模式的做法是将类自身的接口包裹在一个已经存在的类中,包裹的形式可以是组合,也可以是继承,这里可以分成适配器的两种模式:
- 对象适配器模式:适配器关联一个它包裹的类实例(成员变量)
- 类适配器模式:适配器继承被适配的类(一般使用继承的方式)
案例
假设我们现在有接入层UserController
、逻辑层UserService
和持久层UserRepository
,其中UserService
类承载了当前注册register和登录login的功能的核心逻辑。
|
此处我们需要使用适配器模式对其进行扩展,对UserService
进行适配扩展,在不修改原有代码的基础上,适配第三方账号授权登录,复用UserService
的register()
和login()
方法。
接下来我们顺着UML图来进行介绍:
1)被适配(Adaptee)角色
也被称为源角色,当前被适配的角色就是UserService
类,接下来要创建的适配器类就是通过继承这个类来扩展新的功能,复用注册登录方法,实现第三方账号的授权登录。
2)适配器(Adapter)角色
适配器角色,是适配器模式的核心角色。此处它包含第三方账号授权登录的核心逻辑,并通过继承UserService
的方式来复用register()
和login()
方法:
|
上述代码就是开篇说的类适配器模式,它可以很轻松的转换成对象适配器模式:
|
通过对象关联,引入UserService
就是对象适配器模式了。
PS:
此处选择 类适配器模式,也就是通过类继承方式实现适配器模式。
原因:项目开发中,
@Service
标注的类,尽量只提供给@Controller
和@Service
标注的类使用,当然这并非强制性的规定。
3)目标(Target)角色
在创建完适配器角色后,接下来我们需要思考的问题就是:如何创建有关第三方账号登录的方法?是直接创建在适配器类内部吗?
此处呢,需要考虑依赖倒置原则,我们需要面向接口编程。因此,需要创建一个接口,在接口内部声明第三方账号登录相关的方法,这个接口就代表了最终的目标:支持多种类第三方账号登录的功能。
public interface Login3rdTarget { |
然而目标角色只是一个接口类,它必须要被子类实现。此处子类就是适配器类Login3rdAdapter
,因为适配器类才是第三方账号登录功能核心逻辑的实现方
=>
因此,适配器类Login3rdAdapter
在继承UserService
类的同时还需要实现Login3rdTarget
接口
|
总结
写到这里,适配器类就该结束了,接下来就是实现具体的逻辑了。还有两个问题需要思考:
【问题一】Login3rdAdapter
作为适配器Adapter角色,为什么要继承作为被适配Adaptee角色的UserService
类?
【答】:因为要在不修改原有代码的基础上复用UserService
的功能,为适配新的功能做准备,所以需要继承。
【问题二】Login3rdAdapter
作为适配器Adapter角色,为什么要实现作为目标Target角色的Login3rdTarget
接口?
【答】:因为要进行新功能的适配(扩展),Login3rdTarget
代表了第三方账号登录的能力,所以需要继承。
=>
适配器Adapter角色,既能够支持已有功能(账号密码登录注册),也能够适配扩展功能(第三方账号授权登录),适配的扩展功能还可以复用已有的方法(register()
和login()
方法)。