您的位置:首页 > 其它

设计模式之适配器模式

2017-11-17 17:37 211 查看
定义

将一个类的接口转换成客户需要的另一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

结构



client:客户端,调用自己需要的领域接口Target。

target:定义客户端需要的特定领域相关的接口。

adaptee:已经存在的接口,但与客户段要求的特定领域接口不一致,需要被适配。

adapter:适配器,把adaptee适配客户端需要的target.

public interface Target{
void request();
}
public class Adaptee{
public void specificRequest(){
//handle logic
}
}
public class Adapter implements Target{
//持有需要被适配的接口对象
private Adaptee adaptee;
public Adapter(Adaptee adaptee){
this.adaptee = adaptee;
}
public void request(){
//可能转调已经实现的接口方法,进行适配
adaptee.specificRequest();
}
}

public class Client{
public void static main(String[]args){
//创建被适配的对象
Adaptee adaptee = new Adaptee();
//创建客户端需要特定的接口对象(面向接口编程)
Target tagert = new Adapter(adaptee);
//适配器的接口请求
target.request();
}
}


实例 同时支持数据库和文件的日志管理
a. 日志管理第一版

用户要求日志以文件的形式记录

b.日志管理第二版

用户要求日志记录数据库

public class LogModel implements Serializable{
private String logId;
private String operator;
private Date operatorTime;
private String content;
}

//日志文件操作api
public interface LogFileOperateApi{
//文件读
public List<LogModel> readLogFile();
public void writeLogFile(List<LogModel> list);
}

public class LogFileOperate implements LogFileOperateApi{
//读
public List<LogModel> readLogFile(){}
//写
public void writeLogFile(List<LogModel> list){}
}

//日志db 接口
public interface LogDbOperateApi{
//增
public void createLog(LogModel lm);
//删
public void removeLog(LogModel lm);
//改
public void modifyLog(String logId);
//查
public List<LogModel> getLog();
}

public class LogDbOperate implements
LogDbOperateApi{
//增
public void createLog(LogModel lm){}
//删
public void removeLog(LogModel lm){}
//改
public void modifyLog(String logId){}
//查
public List<LogModel> getLog(){}
}

public class Adapter implements LogDbOperateApi{
//持有需要被适配的对象(组合方式)
private LogFileOperateApi adaptee;
public Adapter(LogFileOperate adaptee){
this.adaptee = adaptee;
}
public void createLog(LogModel im){
List<LogModel> list = adaptee.readLogFile();
list.add(lm);
adaptee.writeLogFile(list);
}
public void removeLog(LogModel lm){
List<LogModel> list = adaptee.readLogFile();
list.remove(lm);
adaptee.writeLogFile(list);
}

public void updateLog(String logId){}
public List<LogModel> getLog(){}
}

public class client {
public void static main(String[]args){
LogModel logModel = new LogModel();
List<LogModel> logList = Arrays.asList(logModel);
LogFileOperateApi logFileOperateApi = new LogFileOperateApi();
LogDbOperateApi api = new Adapter(logFileOperateApi);
api.createLog(logModel);
api.getLog();
}
}


理解适配器模式

a. 适配器模式主要功能是进行转化匹配,目的是复用已有的功能,而不是实现新的接口。适配器里面也可以实现功能,这种适配器为之鞥呢适配器。

b. Adaptee 和Target的关系

适配器模式中被适配器Adaptee 和适配转换Target没有关联

c. 对象组合方式实现而不是继承。

d. 时序图

适配器模式的实现

a. 常见实现 通常是一个类,一般会让适配器去实现Taget接口,然后在适配器的具体实现中调用adaptee.

b.智能适配器 在适配器的实现中加入新的功能实现。

c.适配多个Adaptee

d.适配器Adapter复杂程度

取决于Target和Adaptee的相似程度。

e.缺省适配

选择性适配,给具体实现更加灵活。

public class DefaultAdapter implements LogDbOperateApi{
public void createLog(LogModel lm){}
public void removeLog(LogModel lm){}
public void modifyLog(String logId){}
//查
public List<LogModel> getLog(){}
}

public class MyAdapter extends DefaultAdapter{
private LogFileOperateApi adaptee;
private TimeUtil timeUtil;
public MyAdapter(LogFileOperateApi adaptee,TimeUtil timeUtil){
this.adaptee = adaptee;
this.timeUtil = timeUtil;
}
public List<LogModel> getLog(){
adaptee.readLogFile();
}
public void removeLog(LogModel lm){
List<LogModel> list = adaptee.readLogFile();
list.remove(lm);
adaptee.writeLog(list);
}
}


双向适配器

public class TwoDirectAdapter implements LogDbOperateApi,LogFileOperateApi{
private LogFileOperateApi fileLog;
private LogDbOperateApi dbLog;
public TwoDirectAdapater(LogFileOperateApi fileLog,LogDbOperateApi dbLog){
this.fileLog = fileLog;
this.dbLog = dbLog;
}

//db api
public void createLog(LogModel lm){
List<LogModel> list = fileLog.readLogFile();
list.add(lm);
fileLog.writeLogFile(list);
}

public void removeLog(LogModel lm){
List<LogModel> list = fileLog.readLogFile();
list.remove(lm);
fileLog.writeLogFile(list);
}
public void updateLog(){}

//file Api
public List<LogModel> readLogFile(){
return dbLog.getLog();
}

public void writeLogFile(List<LogModel> list){
for(LogModel lm : list){
dbLog.createLog(lm);
}
}
}


类适配器和对象适配器的权衡

类适配器使用对象继承方式,是静态的定义方式;而对象适配器使用对象组合,动态组合的方式。

对于类适配器:由于直接继承adaptee使得适配器不能和Adaptee的自雷一起工作,因为继承了后,就不能再去处理Adaptee的子类。对于对象适配器,允许一个Adapter和多个Adaptee包括和它所有子类一起工作。因为对象适配器采用的是对象组合关系,只要对象正确,是不是子类都无所谓。

对于类适配器:适配器可以重新定义Adaptee的部分欣慰,相当于子类覆盖父类的部分实现方法。对于对象适配器:要重新定义Adaptee的行为比较困难。

对于类适配器:仅仅引入了一个对象,不需要额外的引用来间接得到Adaptee。对于对象适配器,需要额外的引用来间接得到Adaptee.

适配器模式的优缺点

a. 更好的复用性

b. 更好的可扩展性

c.过多的使用适配器,会让系统非常凌乱,不容易整体进行把握。

适配器的本质

转换匹配,复用功能

使用场景

a.使用一个已经存在的类,但它的接口不符合你的需求。可以使用适配器来把已有的实现转换成你的需要的接口。

b.如果想创建一个可以复用的类。这个类可能和一些不兼容的类一起工作。可以使用适配器模式,需要什么就适配什么。

c.如果存在已经存在的子类,但是不可能对每一个子类都进行匹配,这种情况可是用对象适配器,直接适配这些子类的父类就可以。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: