Java设计模式-适配器模式

总的来说这是一个非常简单的适配器,但却非常的好用;另外还补充了个和它差不多的模式:外观模式
首先来看下适配器的定义:
适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
划重点就是:使用对象组合的方式,把一种接口转换成另一种接口;也就是说适配者和被适配者不需要改变任何的代码,只需要在它们中间加一个适配器就可以了
来张图就显得非常好理解了:

适配器.png

适配器分类

实际上有两种适配器,对象适配器和类适配器
对象适配器多是用的组合的方式;类适配器则是用的多继承的方式,因为在 Java 中并不支持多继承,所以类适配器就不演示了,看看对象适配器就好,反正思想都是一样的

对象适配器不仅可以适配某个类,也可以适配该类的任何子类
类适配器非要说的话,Java 中也是可以模拟的,就是适配器继承一个类(源)然后实现一个接口(目标)的方式了
适配器也不一定是单向的,如果实现了双方的接口,也就成了一个双向的适配器

涉及角色

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

一个栗子

既然是把接口转换成另一种接口,那么就先来定义接口吧,就是目标角色和源角色的接口以及它们的实现类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public interface Boy {
void wearClothes();
void eat();
}

public interface Girl {
// 穿女装??!
void wearDress();
void eat();
void prayer();
}
/***************实现类们****************/
public class LovelyGirl implements Girl {
@Override
public void wearDress() {
System.out.println("穿女装 o(*≧▽≦)ツ");
}

@Override
public void eat() {
System.out.println("少女进食中....");
}

@Override
public void prayer() {
System.out.println("少女祈祷中...");
}
}

public class ReliableBoy implements Boy {
@Override
public void wearClothes() {
System.out.println("穿“合适”的衣服");
}

@Override
public void eat() {
System.out.println("男孩吃饭中....");
}
}

然后下面就是关键的适配器了,在这个简单的栗子里是非常的简单的,没什么技术含量…..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class BoyAdapter implements Girl {
private Boy boy;

public BoyAdapter(Boy boy) {
this.boy = boy;
}

@Override
public void wearDress() {
System.out.println("适配/转换中...");
boy.wearClothes();
}

@Override
public void eat() {
boy.eat();
}

@Override
public void prayer() {
System.out.println("我不会....");
}
}

最后来测试下,按照设计原则,尽量的多使用接口,多使用组合..:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Test {
public static void main(String[] args) {
Boy boy = new ReliableBoy();
Girl girl = new LovelyGirl();
BoyAdapter boyAdapter = new BoyAdapter(boy); // 使他看起来像个女孩...

testGirl(girl);
System.out.println("------------------");
testGirl(boyAdapter);
}

// 这个方法需要一个 Girl
public static void testGirl(Girl girl) {
girl.eat(); // 先吃饭
girl.wearDress(); // 穿衣服
girl.prayer(); // 做祷告
}
}

适配器差不多就这个样子了,就是说当目标调用的方法(接口)和期望的不同时,可以转换一下,达到以假乱真的目的,由于调用者使用的是接口,所以它确实不知道你传进来的其实是一个伪娘不同类型的对象

区分

  • 装饰者:不改变接口,但加入责任
    将一个对象包装起来以增加新的行为和责任
  • 适配器:将一个接口转成另一个接口
  • 外观:让接口更简单
    将一群对象“包装”起来以简化其接口
    当需要简化并统一一个很大的接口或者一群复杂的接口时,使用外观模式

外观模式

外观模式也是一个改变接口的模式,但它改变接口的原因是为了简化接口,让其显露出一个干净的外观嘛~~同时它也将客户从组件的子系统中解耦了
一个子系统可以定义多个外观;引入外观之后依然可以调用之前的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Facade {  
private SubSystemA obj1 = new SubSystemA();
private SubSystemB obj2 = new SubSystemB();
private SubSystemC obj3 = new SubSystemC();

public void Method() {
obj1.MethodA();
obj2.MethodB();
obj3.MethodC();
}

public void Method2() {
obj1.MethodA();
obj3.MethodC();
}
}

由于在外观类中维持了对子系统对象的引用,客户端可以通过外观类来间接调用子系统对象的业务方法,而无须与子系统对象直接交互。
另外,它可以让客户端(调用者)的学习成本降低;或者可以配合工厂模式来进行使用
引用的 SubSystem 都应该是接口才对,另外可以提供 setter 方法或者在构造函数中进行延迟初始化
放在这里因为和适配器模式还是有点关联的,并且它非常非常的简单
更多可参考:http://blog.csdn.net/c_son/article/details/51121432

应用举例

还是以 JDK 中的栗子,早先,所有的集合都实现了一个 elements 的方法,用于返回一个枚举,使用枚举来进行迭代元素;
后来开始使用了 Iterator 这个接口,使用迭代器来迭代元素,它还支持删除元素的能力
那么,为了让它和老版本的枚举兼容,就需要使用适配器来进行转换了

在 Android 开发中就有大量的适配器,写过 ListView 的都造是吧?

评论框加载失败,无法访问 Disqus

你可能需要魔法上网~~