设计模式[6]——适配器模式,一分钟彻底说清楚
一句话记住:
适配器模式 = 给老东西插一个“转换头”,让它假装成新东西,继续被新代码愉快使用!
生活例子:
- 美标插头 → 买个国标转换器 → 就能插中国插座
- HDMI 接口电视 → 用一根 HDMI转VGA 线 → 老投影仪也能用
真实业务场景:
新会员系统要求用register(MemberDTO)注册用户,但老系统只有create_user(username, phone, id_card),参数完全对不上。
我们不想改几百个老调用,也不让新系统改接口 → 只能上适配器!
完整可直接跑的业务代码示例:
fromdataclassesimportdataclassimporttime# 新系统要求的 DTO 和接口@dataclassclassMemberDTO:name:strmobile:strid_number:strsource:str="web"classNewMemberService:defregister(self,member:MemberDTO)->str:"""必须实现这个方法,返回会员号字符串"""pass# 老系统 2018 年写的类(全国几百个地方还在用,不能动!)classLegacyUserService:defcreate_user(self,username:str,phone:str,id_card:str)->int:print(f"[老系统] 正在创建用户:{username}")time.sleep(0.1)return1000000+int(time.time()%10000)# 适配器:核心!让老系统“假装”成新接口classMemberAdapter(NewMemberService):def__init__(self,legacy:LegacyUserService):self.legacy=legacydefregister(self,member:MemberDTO)->str:# 把新 DTO 转成老系统认识的参数old_id=self.legacy.create_user(username=member.name,phone=member.mobile,id_card=member.id_number)# 老系统返回 int,新系统要字符串会员号new_member_id=f"MBR{old_id:010d}"print(f"适配成功 →{old_id}→{new_member_id}")returnnew_member_id# 业务代码(完全不知道底层是用老系统还是新系统)defregister_vip(service:NewMemberService):dto=MemberDTO(name="李四",mobile="18812345678",id_number="310101199912120000")mid=service.register(dto)print(f"注册完成,会员号:{mid}\n")# 使用:只差一行代码决定用新还是老if__name__=="__main__":# 现在还得兼容老系统 → 插上适配器adapter=MemberAdapter(LegacyUserService())# 未来换真新系统时,只需要把上面这行换掉就行# adapter = RealNewMemberService()register_vip(adapter)输出:
[老系统] 正在创建用户:李四 适配成功 → 1003721 → MBR0001003721 注册完成,会员号:MBR0001003721经典结构图(记这个就终身不忘):
客户端 → 目标接口(NewMemberService) ↑ 适配器 Adapter ↑ 已有的老类(LegacyUserService)总结三句话:
- 新接口不兼容老实现?写个适配器就行
- 适配器就是“转换头”,两边接口对得上就完事
- 公司里最常见模式之一:对接第三方、系统迁移、历史包袱,全靠它救命!
适配器模式,30秒看懂,工作中天天用!搞定!