【设计模式】适配器模式:攻敌三分,自留七分,以超兽武装的例子来谈谈适配器模式
1 适配器模式
1.1 定义
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能在一起工作的那些类能一起工作。
适配器模式分为类适配器模式和对象适配器模式,前者类(类适配器)之间的耦合度比后者高,而且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对少一些。
1.2 结构
目标接口(Target):当前系统业务所期待的接口,它可以是抽象类或者接口。
适配者类(Adaptee):他是被访问和适配的现存组件库中的组件接口。
适配器类(Adapter):它是一个转换器,通过**继承(类)或引用(对象)**适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
个人认为:适配器的作用就是让用户使用 A 的功能而达到 B 功能的效果。
1.3 类图
1.3.1 类适配器模式
1.3.2 对象适配器模式
为什么要有对象适配器模式,因为类适配器模式违反了合成/聚合复用原则,也就是优先考虑组合/聚合来实现复用,其次考虑继承(使用继承需要严格遵循里氏代换原则,滥用继承会增加系统构建和维护的难度以及系统的复杂度)
2 例子
国产动画片《超兽武装》中的角色就很符合适配器模式。他们可以以普通模式进行战斗,也可以通过异能锁(适配器)来召唤超兽武装进行战斗。角色(如龙戬)想要发送技能--寒影决,通过异能锁,将其变成了威力更为强大的超兽形态寒影决。
普通形态的龙戬
也可以攻击和使用寒影决
异能锁
借助异能锁,超兽武装,将自己的寒影决变成超兽武装的寒影决,威力更大
超兽武装
可以攻击、使用超兽状态下的寒影决
2.1 类适配器模式
2.1.1 代码
在此例子中,有四个重要的角色 龙戬(DargonJian)、普通形态(Common)、超兽武装形态(Mocha)、异能锁(PowerLock)。使用适配器的目的即为龙戬在使用普通形态的技能时底层调用的是超兽武装形态的技能方法。
至于为什么是类适配器模式而不是对象适配器模式,核心就在于在将普通形态接口转化成超兽武装形态的过程中,适配器类继承了超兽武装形态的实现类,而不是创建一个超兽武装形态类的对象。
Common.interface
CommonImpl.java
Mocha.interface
MochaImpl.java
PowerLock.java
DargonJian.java
Client.java
2.1.2 效果图
2.2 对象适配器模式
这里为了符合合成/聚合复用原则,将原有的继承改成了组合/聚合的形式
2.2.1 代码
Client.java
Common.java
CommonImpl.java
DragonJian.java
Mocha.java
MochaImpl.java
PowerLock.java
2.2.2 效果通
3 优缺点及适用环境
3.1 优点
一个对象适配器可以把多个不同的适配器适配到同一个目标
可以适配一个适配者的子类,由于适配器和适配者之间是关联关系,根据"里氏代换原则",适配者的子类也可以通过该适配器进行适配。
将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无需修改原有的代码。增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
3.2 缺点
对于 Java、C#等不支持多重类继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者。
在 Java、C#等语言中,类适配者模式中的目标抽象类只能为接口,不能为类,其使用有一定的局限性。
3.3 适用环境
系统需要使用现有的类,而这些类的接口不符合系统的需要。想要建立一个可以重复使用的类,用于一些彼此之间没有太大关联的类,包括一些可能在将来引进的类一起工作。是关联关系,根据"里氏代换原则",适配者的子类也可以通过该适配器进行适配。
评论