大话设计模式笔记(十四)の适配器模式
举个栗子
问题描述
不同国家的人在NBA打球,但都是用英文交流。
简单实现
Player
1. /**
2. * 球员
3. * Created by callmeDevil on 2019/8/4.
4. */
5. public abstract class Player {
6.
7. protected String name;
8.
9. public Player(String name){
10. this.name = name;
11. }
12.
13. // 发起进攻
14. public abstract void attack();
15. // 转回防守
16. public abstract void defense();
17.
18. }
19.
Forwards
1. /**
2. * 前锋
3. * Created by callmeDevil on 2019/8/4.
4. */
5. public class Forwards extends Player {
6.
7. public Forwards(String name){
8. super(name);
9. }
10.
11. @Override
12. public void attack() {
13. System.out.println(String.format("前锋 %s 进攻", name));
14. }
15.
16. @Override
17. public void defense() {
18. System.out.println(String.format("前锋 %s 防守", name));
19. }
20. }
21.
Center
1. /**
2. * 中锋
3. * Created by callmeDevil on 2019/8/4.
4. */
5. public class Center extends Player {
6. // 代码与前锋相似
7. }
8.
Guards
1. /**
2. * 后卫
3. * Created by callmeDevil on 2019/8/4.
4. */
5. public class Guards extends Player {
6. // 代码与前锋相似
7. }
8.
测试
1. public class Test {
2. public static void main(String[] args) {
3. Player b = new Forwards("巴蒂尔");
4. b.attack();
5. Player m = new Guards("麦克格雷迪");
6. m.attack();
7.
8. Player ym = new Center("姚明");
9. // 姚明问:attack 和 defense 是什么意思?
10. ym.attack();
11. ym.defense();
12. }
13. }
14.
测试结果
1. 前锋 巴蒂尔 进攻
2. 后卫 麦克格雷迪 进攻
3. 中锋 姚明 进攻
4. 中锋 姚明 防守
5.
存在问题
姚明刚到NBA时可能英文还不太好,也就是说听不懂教练的战术安排,attach 和 defense 不知道什么意思,因此这样实现会有问题,需要一个中英翻译。
适配器模式
定义
将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
分类
主要分为类适配器模式和对象适配器模式。由于类适配器模式通过多重继承对一个接口与另一个接口进行匹配,而 Java 等语言不支持多重继承,也就是一个类只有一个父类,所以这里主要讲的是对象适配器。
UML图
代码实现
ForeignCenter
1. /**
2. * 外籍中锋
3. * Created by callmeDevil on 2019/8/4.
4. */
5. public class ForeignCenter {
6.
7. // 外籍中锋球员的姓名故意用属性而不是构造方法来区别与三个球员的不同
8. private String name;
9.
10. // 表明外籍中锋只懂中文“进攻”(注意:举例效果,实际上千万别用这种方式编程)
11. public void 进攻(){
12. System.out.println(String.format("外籍中锋 %s 进攻", name));
13. }
14.
15. // 表明外籍中锋只懂中文“防守”(注意:举例效果,实际上千万别用这种方式编程)
16. public void 防守(){
17. System.out.println(String.format("外籍中锋 %s 防守", name));
18. }
19.
20. public String getName() {
21. return name;
22. }
23.
24. public void setName(String name) {
25. this.name = name;
26. }
27. }
28.
Translator
1. /**
2. * 翻译者
3. * Created by callmeDevil on 2019/8/4.
4. */
5. public class Translator extends Player{
6.
7. // 声明并实例化一个内部“外籍中锋”对象,表明翻译者与外籍球员有关联
8. private ForeignCenter wjzf = new ForeignCenter();
9.
10. public Translator(String name){
11. super(name);
12. wjzf.setName(name);
13. }
14.
15. @Override
16. public void attack() {
17. // 翻译者将“attack”翻译为“进攻”告诉外籍中锋
18. wjzf.进攻();
19. }
20.
21. @Override
22. public void defense() {
23. // 翻译者将“defense”翻译为“防守”告诉外籍中锋
24. wjzf.防守();
25. }
26.
27. }
28.
测试
1. public class Test {
2. public static void main(String[] args) {
3. Player b = new Forwards("巴蒂尔");
4. b.attack();
5. Player m = new Guards("麦克格雷迪");
6. m.attack();
7.
8. Player ym = new Translator("姚明");
9. // 翻译者告诉姚明,教练要求你既要“进攻”又要“防守”
10. ym.attack();
11. ym.defense();
12. }
13. }
14.
测试结果
1. 前锋 巴蒂尔 进攻
2. 后卫 麦克格雷迪 进攻
3. 外籍中锋 姚明 进攻
4. 外籍中锋 姚明 防守
5.
总结
- 系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。
- 适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。
- 使用已经存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就应该考虑用适配器模式。
- 两个类所做的事情相同或相似,但是具有不同的接口时要使用它。
- 客户代码可以统一调用同一接口就行了,这样可以更简单、直接、紧凑。
- 在双方都不太容易修改的时候再使用适配器模式适配。
Pass:以上纯属个人理解~~如果发现有错或是心存建议意见等,欢迎大家评论或联系~(# ゚Д゚)~祝大家身体健康学习进步工作顺利生活愉快!
版权归 callmeDevil 所有,如需转载请标注转载来源
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(三):用.NET IoT库
· 【非技术】说说2024年我都干了些啥