适配器模式之对象适配器

简介:

  问题导入:比如有A型螺母和B型螺母,那么用户可以再A型螺母上直接使用按着A型螺母生产的A型螺丝,同样也可以在B型螺母上直接使用按着B型 螺母标准生产的B型螺丝。但是由于A型螺母和B型螺母的标准不一样,用户在A型螺母上不能直接使用B型的螺丝,反之也一样。该如何达到这个目的呢?

  使用适配器就可以解决这个问题:生产一种“A型螺母适配器”,这种A型螺母适配器的前端符合A型螺母标准要求,可以拧在A型螺母上,后端又焊接了一个B型螺母。这样用户就可以借助A型螺母适配器在A型螺母上使用B型的螺丝了。

  适配器模式又称为包装器,是用来将一个类的接口转换成客户希望的另外一个接口。这可以使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。适配器模式的关键是建立一个适配器,这个适配器实现了目标接口并且包含了被适配者的引用。

适配器模式的三种角色:

  一、目标:目标是一个接口,该接口是客户想要使用的接口。

  二、被适配者:被适配者是一个已经存在的接口或抽象类,这个接口接口或者抽象类需要适配。

  三、适配器:适配器是一个类,该类实现了目标接口并且包含有被适配者的引用,即适配器的职责是对适配者接口或抽象类与目标接口进行适配。

  以下通过一个简单的问题来描述适配器模式中所涉及的各个角色。

  用户已经有一个两厢的插座,但是最近用户又有了一个新的三厢插座。用户现有一台洗衣机和一台电视机,洗衣机是三厢插头,而电视机是两厢插头。现在用户想用心的三厢插座来使用洗衣机和电视机,即用心的三厢插座为洗衣机和电视机接通电流。

  针对以上问题,使用适配器模式设计若干个类。

  1.目标

  本问题是使用三厢插座来为电视机和洗衣机接通电流,所以目标是三厢插座。把三厢插座设置为一个接口:

1 package com.adatpe;
2
3 //适配目标:三相插座
4 public interface ThreeElectricOutlet {
5     void connectElectricCurrent();
6 }

 2.被适配者

  对于本问题,用户是想要用三厢插座为两厢插头的电视机接通电流,所以被适配者应该是两厢插座,也设置为一个接口:


1 package com.adatpe;
2
3 //被适配者:两相插座
4 public interface TwoElectricOutlet {
5     void connectElectricCurrent();
6 }


  3.适配器

  该适配器实现了目标接口三厢插座ThreeElectricOutlet,同时又包含了两厢插座TwoElectricOutlet的引用:


 1 package com.adatpe;
 2
 3 //适配器:实现目标接口
 4 public class ThreeElectricAdapter implements ThreeElectricOutlet {
 5     //适配器包含被适配者的引用
 6     private TwoElectricOutlet outlet;
 7     public ThreeElectricAdapter(TwoElectricOutlet outlet) {
 8         this.outlet = outlet;
 9     }
10     public void connectElectricCurrent() {
11         outlet.connectElectricCurrent();
12     }
13
14 }


  下列应用程序中,Application.java使用了适配器模式中所涉及的类,应用程序负责用Wash类创建一个对象来模拟一台洗衣机,使用TV类创建一个对象来模拟一台电视机

使用ThreeElectricOutlet接口变量调用Wash对象的connectElectricCurrent()方法,并借助适配器调用TV对象的connectElectricCurrent()方法,即用三厢插座分别为洗衣机和电视机接通电流。


 1 package com.adatpe;
 2
 3 public class Application {
 4     public static void main(String[] args) {
 5         ThreeElectricOutlet outlet; //目标接口(三相插座)
 6         Wash wash = new Wash();     //洗衣机
 7         outlet = wash;              //洗衣机插在三相插座上
 8         System.out.println(“使用三相插座接通电流”);
 9         outlet.connectElectricCurrent();    //接通电流开始洗衣服
10         TV tv = new TV();           //电视机
11         ThreeElectricAdapter adapter = new ThreeElectricAdapter(tv); //把电视插在适配器上面
12         outlet = adapter;           //再把适配器插在三厢插座上
13         System.out.println(“使用三厢插座接通电流”);
14         outlet.connectElectricCurrent();  //接通电流,开始播放电视节目
15     }
16 }
17
18 //洗衣机使用三相插座
19 class Wash implements ThreeElectricOutlet{
20     private String name;
21     public Wash() {
22         name = “黄河洗衣机”;
23     }
24     public Wash(String name){
25         this.name = name;
26     }
27     public void connectElectricCurrent() {
28         turnOn();
29     }
30     public void turnOn(){
31         System.out.println(name+”开始洗衣服了”);
32     }
33 }
34
35
36 //电视机使用两厢插座
37 class TV implements TwoElectricOutlet{
38     private String name;
39     public TV() {
40         name = “长江电视机”;
41     }
42     public TV(String name){
43         this.name = name;
44     }
45     public void connectElectricCurrent() {
46         turnOn();
47     }
48     public void turnOn(){
49         System.out.println(name+”开始播放电视节目”);
50     }
51
52 }

运行结果为:

使用三相插座接通电流
黄河洗衣机开始洗衣服了
使用三厢插座接通电流
长江电视机开始播放电视节目

 

下面举个双向适配器的例子

  在适配器模式中,如果Adapter角色同时实现目标接口和被适配者接口,并包含目标接口和被适配接口的引用,那么该适配器就是一个双向适配 器。使用双向适配器,用户既可以用新的接口又可以用已有的接口。在以上例子中,如果用户希望能有三厢插座来接通洗衣机和电视机的电流,有可以用两厢插座来 接通洗衣机和电视机的电流,那么就必须使用一个双向适配器。具体代码如下:


 1 package com.adatpe;
 2
 3 public class ThreeAndTwoElectricAdapter implements ThreeElectricOutlet,
 4         TwoElectricOutlet {
 5     private ThreeElectricOutlet threeElectricOutlet;
 6     private TwoElectricOutlet twoElectricOutlet;
 7     public ThreeAndTwoElectricAdapter(ThreeElectricOutlet threeOutlet,TwoElectricOutlet twoOutlet) {
 8         threeElectricOutlet = threeOutlet;
 9         twoElectricOutlet = twoOutlet;
10     }
11     public ThreeAndTwoElectricAdapter(TwoElectricOutlet twoOutlet,ThreeElectricOutlet threeOutlet){
12         threeElectricOutlet = threeOutlet;
13         twoElectricOutlet = twoOutlet;
14     }
15     public void connectElectricCurrent() {
16         if(this instanceof ThreeElectricOutlet){
17             twoElectricOutlet.connectElectricCurrent();//twoElectricOutlet是被适配的接口
18         }
19         if(this instanceof TwoElectricOutlet){
20             threeElectricOutlet.connectElectricCurrent(); //threeElectricOutlet是被适配的接口
21         }
22     }
23     public static void main(String[] args) {
24         ThreeElectricOutlet threeOutlet;
25         TwoElectricOutlet twOutlet;
26         Wash wash = new Wash();
27         TV tv = new TV();
28         ThreeAndTwoElectricAdapter adapter = new ThreeAndTwoElectricAdapter(wash,tv);
29         threeOutlet = adapter;
30         System.out.println(“使用三厢插座接通电源”);
31         threeOutlet.connectElectricCurrent();
32         twOutlet = adapter;
33         System.out.println(“使用两厢插座接通电源”);
34         twOutlet.connectElectricCurrent();
35     }
36
37 }

运行结果为:

使用三厢插座接通电源
长江电视机开始播放电视节目
黄河洗衣机开始洗衣服了
使用两厢插座接通电源
长江电视机开始播放电视节目
黄河洗衣机开始洗衣服了

这样就实现了即可以用三厢插座又可以用两厢插座来为电视机和洗衣机接通电流了。

使用适配器模式主要有以下优点:

  1.目标和被适配者是完全解耦的关系。

  2.适配器模式满足“开–闭原则”,当添加一个实现了Adapter接口的新类时,不必修改Adapter,Adapter就能对这个新类的实例进行适配。

 


相关文章
|
5月前
|
设计模式
|
设计模式 Java 数据库
JAVA设计模式2:工厂方法模式,将对象的实例化过程封装在子类
JAVA设计模式2:工厂方法模式,将对象的实例化过程封装在子类
108 0
|
8月前
|
设计模式 uml
设计模式-适配器模式(对象适配器)
设计模式-适配器模式(对象适配器)
47 0
|
消息中间件 设计模式 移动开发
装饰器模式:让你的对象变得更强大
在日常开发中,当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。这时候,我们该怎么办呢?我们可以使用装饰器器模式来解决这个问题,本文将从以下五个方面讲解装饰器器模式。
60 0
适配器的作用
适配器的作用
191 0
|
设计模式 前端开发 Java
设计模式之适配器模式(类适配器、对象适配器、源码体现)
设计模式之适配器模式(类适配器、对象适配器、源码体现)
99 0
|
算法 C++
C++函数适配器
C++函数适配器
|
设计模式 Java
浅析Java设计模式【2.2】——适配器
Java常用设计模式,适配器模式
94 0
浅析Java设计模式【2.2】——适配器
|
设计模式
结构型-Adapter
适配器模式的原理与实现 适配器模式 的英文翻译是 Adapter Design Pattern。顾名思义,这个模式就是用来做适配的,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。对于这个模式,有一个经常被拿来解释它的例子,就是 USB 转接头充当适配器,把两种不兼容的接口,通过转接变得可以一起工作。 原理很简单,我们再来看下它的代码实现。适配器模式有两种实现方式:类适配器和对象适配器。其中,类适配器使用继承关系来实现,对象适配器使用组合关系来实现。具体的代码实现如下所示。其中,ITarget 表示要转化成的接口定义。Adaptee 是一组不兼容 ITa
123 0
结构型-Adapter
|
设计模式
【设计模式】适配器模式 ( 类适配器代码模板 | 对象适配器代码模板 | 适配器模式示例 )
【设计模式】适配器模式 ( 类适配器代码模板 | 对象适配器代码模板 | 适配器模式示例 )
130 0