lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

         假如我们又这样软件系统,我们希望它能够和一个新的库搭配使用,但是这个库所提供的接口与我们的软件系统不兼容,我们不想改变现有代码就能解决这个问题,怎么办?这个时候我们就需要将这个新的库接口转换成我们所需要的接口,这就是适配器模式设计动机。 

         一、模式定义

         何谓适配器模式?适配器模式就是将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。

         在适配器模式中,我们可以定义一个包装类,包装不兼容接口的对象,这个包装类就是适配器,它所包装的对象就是适配者。

         适配器提供给客户需要的接口,适配器的实现就是将客户的请求转换成对适配者的相应的接口的引用。也就是说,当客户调用适配器的方法时,适配器方法内部将调用适配者的方法,客户并不是直接访问适配者的,而是通过调用适配器方法访问适配者。因为适配器可以使互不兼容的类能够“合作愉快”。

 

         二、模式结构                                                                                                                                                                                                            

         这个适配器模式充满着良好的OO设计原则:使用对象组合,以修改的接口包装别适配者。而且这样做还有一个优点,被适配者的任何子类,都可以搭配适配器使用。

         适配器模式有如下四个角色:

            Target:目标抽象类

            Adapter:适配器类

            Adaptee:适配者类

            Client:客户类

 

         三、模式实现                                                                                                  

         在这里我们模拟一个机器人。首先我们拥有一个机器人,它可以叫(cry),跑(run)。现在我们希望它能够像小狗一样叫,像小狗一样跑。

         首先我们需要一个机器人接口:Robot.java。提供cry()和run()方法。

 

public interface Robert {
void cry();
void move();
}

         然后是一个仿生机器人:BioRobot.java。它可以叫和慢慢跑

public class BioRobert implements Robert {
public void cry() {
System.out.println("仿生机器人叫.....");
}

public void move() {
System.out.println("仿生机器人慢慢移动....");
}
}

         然后是小狗:Dog.java。可以旺旺叫和快快跑。

public class Dog {
public void wang() {
System.out.println("小狗叫:汪汪.....");
}

public void run() {
System.out.println("小狗快快跑......");
}
}

         轮到重点啦:适配器,这个适配器能够使仿生机器人像狗一样叫,一样跑。

public class DogAdapter implements Robert {
private Dog dog;

public DogAdapter(Dog dog) {
this.dog = dog;
}

@Override
public void cry() {
System.out.println("机器人模仿小狗叫");
dog.wang();
}

@Override
public void move() {
System.out.println("机器人模仿小狗跑");
dog.run();
}
}

         客户端:Client.java

public class Client {
public static void main(String[] args) {
Dog dog = new Dog();
Robert dogRobert = new DogAdapter(dog);
System.out.println("birRobert .....");
dogRobert.cry();
dogRobert.move();
}
}

       运行结果。

birRobert .....
机器人模仿小狗叫
小狗叫:汪汪.....
机器人模仿小狗跑
小狗快快跑......

         如果我们希望这个仿生机器人能够像鸟一样唧唧的叫和飞呢?只需要添加一个能够叫和飞的鸟类以及一个鸟的适配器即可。如下:

public class Bird {
public void jiji() {
System.out.println("小鸟叽叽喳喳的叫");
}

public void fly() {
System.out.println("小鸟飞起来");
}

}
public class BirdAdapter implements Robert {
private Bird bird;

public BirdAdapter(Bird bird) {
this.bird = bird;
}

@Override
public void cry() {
System.out.println("机器人模仿小鸟叫");
bird.jiji();
}

@Override
public void move() {
System.out.println("机器人模仿小鸟飞");
bird.fly();
}
}

 

         四、模式优缺点                                                                                                    

           优点

              1.  将目标类和适配者类解耦,通过使用适配器让不兼容的接口变成了兼容,让客户从实现的接口解耦。

              2. 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。

              3. 灵活性和扩展性都非常好在不修改原有代码的基础上增加新的适配器类,符合“开闭原则”。

 

         五、使用场景                                                                                                     

         1. 系统需要使用现有的类,而这些类的接口不符合系统的需要。

         2.想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类

 

         六、模式扩充                                                                                                     

         适配器模式分为对象适配器和类适配器。前面所概述的是对象适配器。为什么没有将类适配器呢?因为类适配器需要使用多重继承,这个在java中没有办法实现的。但是当我们遇到可以使用多重继承语言的时候,还是可能会遇到这种需求。

         类适配器模式UML图。

         在类适配器中,由于适配器是适配者的子类,所以可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。但是对于一些不支持多重继承的编程语言来说(Java ,C#),其使用就会存在一定的局限性:不能将一个适配者类和它的子类都适配到目标接口。

         对于对象适配器而言,一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。但是如果我们需要置换掉适配者的某些方法时,这个实现就会比较难,我们首先要先做一个适配者的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。

 

  七、总结                                                                                    

         1、当我们需要使用的一个现有的类,但是他的接口并不符合我们的需求时,我们可以使用适配器模式。

         2、适配器模式分为类适配器和对象适配器,其中类适配器需要用到多重继承。

posted on 2019-05-01 20:17  白露~  阅读(721)  评论(0编辑  收藏  举报