您的位置:首页 > 其它

设计模式之适配器模式

2018-01-11 12:01 211 查看

设计模式之适配器模式

一、适配器模式介绍

适配器是将两个不兼容的类融合在一起,将不同的东西通过一种转化使得他们能够协作起来。

二、适配器模式的定义

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

三、适配器模式的使用场景

1、系统需要使用现有的类,而此类的接口不符合系统需求,即接口不兼容。

2、想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。

3、需要一个统一的输出接口,而输入端的类型不可预知。

四、适配器模式的分类

适配器模式分为两类,即类适配器模式和对象适配器模式。

1、类适配器模式

1.1 UML结构图如下:



如上图所示,类适配器是通过实现Target接口以及继承Adaptee类来实现接口转换,例如目标接口需要的是operation2,但是Adaptee对象只有一个operation3,因此就出现了不谦容的情况。此时通过Adapter实现一个operation2函数将Adaptee的operation3转换为Target需要的operation2,以此实现兼容。

1.2 角色的划分

Target: 目标角色,也就是所期待得到的接口。注意:由于这里讨论的是类适配器模式,因此目标不可以是类。

Adaptee: 现在需要适配的接口。

Adapter: 适配器角色,也是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。

2、对象适配器模式

与类适配器模式一样,对象的适配器模式把被适配的类的API转换为目标类的API,与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用代理关系链接到Adapter类,UML图如下:



从上图可以看出,Adaptee类(Volt220)并没有getVolt5()方法,而客户端期待这个方法。为使客户端能够使用Adaptee类,需要提供一个包装类Adapter.这个包装类包装了一个Adaptee的实例,从而此包装类能够把Adaptee的API与Target类的API衔接起来。Adapter与Adaptee是委派关系,这决定了适配器模式是对象的。

五、适配器模式应用的简单示例

用笔记本电源转换器为例 要将220V–>5V 来匹配笔记本使用

在这个示例中

5V电压就是Target接口

220V电压就是Adaptee类

将电压从220V转换到5V就是Adapter.

类适配器模式具体的程序如下:

/**
* Target角色
*
* @author chenyongliang
* @time 2018/1/11 上午10:55
*/
public interface FiveVolt {

public int getVolt5();
}


/**
* Adaptee 角色,需要被转换的对象
*
* @author chenyongliang
* @time 2018/1/11 上午10:57
*/
public class Volt220 {

public int getVolt220() {
return 220;
}

}


/**
* Adapter 角色,将220V的电压转换成5V的电压
* @author chenyongliang
* @time 2018/1/11 上午11:01
*/
public class VoltAdapter extends Volt220 implements FiveVolt {
@Override
public int getVolt5() {
return 5;
}
}


Target角色给出了需要的目标接口,二Adaptee类则是需要被转换的对象。Adapter则是将Volt220转换成Target的接口。对应的目标是要获取5V的输出电压,而Adaptee正常输出电压是220V,此时就需要电源适配器类将220V的电压转换为5V电压,解决接口不兼容的问题。

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

VoltAdapter adapter = new VoltAdapter();
Log.e("","输出电压:"+adapter.getVolt5());
}
}


测试结果:



对象适配器 示例代码如下:

/**
* Target角色
*
* @author chenyongliang
* @time 2018/1/11 上午10:55
*/
public interface FiveVolt {

public int getVolt5();
}


/**
* Adaptee 角色,需要被转换的对象
*
* @author chenyongliang
* @time 2018/1/11 上午10:57
*/
public class Volt220 {

public int getVolt220() {
return 220;
}

}


/**
* 对象适配器模式
*
* @author chenyongliang
* @time 2018/1/11 上午11:01
*/
public class VoltAdapter implements FiveVolt {

Volt220 mVolt220;

public VoltAdapter(Volt220 mVolt220) {
this.mVolt220 = mVolt220;
}

public int getVolt220() {
return mVolt220.getVolt220();
}

@Override
public int getVolt5() {
return 5;
}
}


使用示例:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//类适配器测试
//        VoltAdapter adapter = new VoltAdapter();
//        Log.e("","输出电压:"+adapter.getVolt5());

//对象适配器测试
VoltAdapter adapter = new VoltAdapter(new Volt220());
Log.e("","输出电压:"+adapter.getVolt5());
}
}


测试结果:



这种方式实现,直接将要被适配的对象传递到Adapter中,使用组合的形式实现接口兼容的效果。这比类适配方式更为灵活,它的另一个好处是被适配的对象中的方法不会暴露出来,而类适配器由于继承了被适配对象,因此,被适配对象类的函数再Adapter类中也都含有,这使得Adapter类出现一些奇怪的接口,用户使用成本较高。因此,对象适配器模式更加灵活、实用。

总结:在使用Adapter模式的过程中建议尽量使用对象适配器的实现方式,多用合成或者聚合,少用继承。当然具体问题具体分析,根据需要来选用实现方式,最合适的才是最好的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: