设计模式学习(二)适配器模式

适配器模式

介绍

适配器模式:适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

图示
这里写图片描述

模式所涉及的角色有:

  • 目标(Target)角色:这就是所期待得到的接口。注意:由于这里讨论的是类适配器模式,因此目标不可以是类。
  • 源(Adapee)角色:现在需要适配的接口。
  • 适配器(Adaper)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。

实现的方式:
(1)类的适配器模式(采用继承实现)
(2)对象适配器(采用对象组合方式实现)
适配器模式的类图
这里写图片描述

场景:不管大家能否接受手机取消3.5毫米耳机孔,但是这已经成为大趋势,苹果都这么干了,就只会有越来越多的跟随者,如果想用耳机听音乐,就要接入type-c转3.5mm耳机接口,这里就需要一个适配器模式了。

一、类的适配器模式代码实现

//已存在的、具有特殊功能、但不符合我们既有的标准接口的Adaptee类  3.5毫米耳机接口 
public class ThreePointFiveMM {
        public void SpecialRequest() {
            System.out.println("被适配的类      具有特殊的听歌功能......");
        }
}

//目标接口,或称为标准接口
public interface Target {
  public void Request();
}

//具体目标类,只提供普通功能    (Typec接口,提供充电)
public class Typec implements Target {
    @Override
    public void Request() {
        System.out.println("普通的Typec类      具有普通的充电功能......");
    }
}

//适配器类,继承了被适配类,同时实现标准接口  (typec转3.5毫米耳机接口)  
public class TypecTo3Point5MM extends ThreePointFiveMM implements Target {
    @Override
    public void Request() {
        super.SpecialRequest();
    }
}

//测试类
public class Client {
    public static void main(String[] args) {
        //使用普通功能类
            Target  typec = new Typec();
            typec.Request();
            //使用特殊功能类,即适配类
            Target typecTo3Point5mm = new TypecTo3Point5MM();
            typecTo3Point5mm.Request();
    }
}

测试结果:
这里写图片描述

上面这种实现的适配器称为类适配器,因为 TypecTo3Point5MM(Adapter) 类既继承了 ThreePointFiveMM(Adaptee) (被适配类),也实现了 Target 接口(因为 Java 不支持多继承,所以这样来实现),在 Client 类中我们可以根据需要选择并创建任一种符合需求的子类,来实现具体功能。另外一种适配器模式是对象适配器,它不是使用多继承或继承再实现的方式,而是使用直接关联,或者称为委托的方式,类图如下:

这里写图片描述
代码如下

//适配器类,直接关联被适配类,同时实现标准接口  
public class TypecTo3Point5MM implements Target {
     // 直接关联被适配类  
    ThreePointFiveMM mThreePointFiveMM;
    // 可以通过构造函数传入具体需要适配的被适配类对象 
     public TypecTo3Point5MM(ThreePointFiveMM mThreePointFiveMM) {
         this.mThreePointFiveMM=mThreePointFiveMM;      
    }
    @Override
    public void Request() {
        // 这里是使用委托的方式完成特殊功能  
        this.mThreePointFiveMM.SpecialRequest();
    }
}

//测试类
public class Client {
    public static void main(String[] args) {
        //使用普通功能类
            Target  typec = new Typec();
            typec.Request();
        // 使用特殊功能类,即适配类,  
        // 需要先创建一个被适配类的对象作为参数  
            Target typecTo3Point5mm = new TypecTo3Point5MM(new ThreePointFiveMM());
            typecTo3Point5mm.Request();
    }
}

测试结果与上面的一致。从类图中我们也知道需要修改的只不过就是 TypecTo3Point5MM(Adapter) 类的内部结构,即 Adapter 自身必须先拥有一个被适配类的对象,再把具体的特殊功能委托给这个对象来实现。使用对象适配器模式,可以使得 Adapter 类(适配类)根据传入的 ThreePointFiveMM(Adaptee) 对象达到适配多个不同被适配类的功能,当然,此时我们可以为多个被适配类提取出一个接口或抽象类。这样看起来的话,似乎对象适配器模式更加灵活一点。

总结

优点:
1. 通过适配器,客户端可以调用同一接口,因而对客户端来说是透明的。这样做更简单、更直接、更紧凑。增加了类的透明度。
2. 复用了现存的类,解决了现存类和复用环境要求不一致的问题。提高了类的复用
3. 将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。
4. 一个对象适配器可以把多个不同的适配者类适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。灵活性好。

缺点:
1. 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
2. 由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。

使用场景:
(1)系统需要使用现有的类,而此类的接口不符合系统的需要。
(2)想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有很复杂的接口。
(3)两个类所做的事情相同或相似,但是具有不同接口的时候。
有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值