设计模式:Adapter模式

Adapter适配器,一般喜欢拿交流电转换成直流电的适配器来举例,可以简单理解成一个转接头的功能,使得能够相互满足需求

Adapter模式有两种方式:

类适配器模式:使用继承

对象适配器模式:使用委托

将原本不匹配的接口转换成期待的另一种接口;由于涉及模式宗旨就是提升代码的复用率,具体还是他通过例子code来进行说明

(1)类适配器模式

一个需求,将输入的字符串,做一些适配相关的操作的处理,比如输入Hello,那么要求输出(Hello)和*Hello*,例子很简单,定义成具体的类:

Banner类:实际传入的信息,相当于交流220V,或者是上面的Hello

PrintBanner类:具体的适配器,进行转换

Print接口:需求转换后输出的,比如直流xxV,或者(Hello)和*Hello*

首先目标接口Print,也就是需求的接口

package adapter;

/**
* Copyright (C), 2014-2018, maoxiaomeng.com
* FileName: Print
* Author: lihui
* Date: 2018/4/29 12:20
*/

public interface Print {
public abstract void printWeak();
public abstract void printStrong();
}

定义Banner类,

package adapter;

/**
* Copyright (C), 2014-2018, maoxiaomeng.com
* FileName: Banner
* Author: lihui
* Date: 2018/4/29 12:18
*/

public class Banner {
private String string;
public Banner(String string) {
this.string = string;
}

public void showWithParen() {
System.out.println("(" + string + ")");
}

public void showWithAster() {
System.out.println("*" + string + "*");
}
}

下面就是一个适配器PrintBanner类,让它继承Banner类并实现了新的需求Print接口

package adapter;

/**
* Copyright (C), 2014-2018, maoxiaomeng.com
* FileName: PrintBanner
* Author: lihui
* Date: 2018/4/29 12:20
*/

public class PrintBanner extends Banner implements Print {
public PrintBanner(String string) {
super(string);
}

public void printWeak() {
showWithParen();
}

public void printStrong() {
showWithAster();
}
}

最后是main

package adapter;

/**
* Copyright (C), 2014-2018, maoxiaomeng.com
* FileName: Main
* Author: lihui
* Date: 2018/4/29 12:25
*/

public class Main {
public static void main(String[] args) {
Print p = new PrintBanner("Hello");
p.printWeak();
p.printStrong();
}
}

在Main中,PrintBanner实例保存在Print类型变量p中,最终都是在printWeak,printStrong来重写实现,而Main里Banner类和showWithXX都被隐藏起来了;也就是调用者只需要直流电,只需要输出带()和**,至于说其实是被适配器由交流电转换来的,并不关心;修改PrintBanner的实现,也不影响Main的调用

(2)对象适配器模式

将Print改为抽象类

package adapter;

/**
* Copyright (C), 2014-2018, maoxiaomeng.com
* FileName: Print
* Author: lihui
* Date: 2018/4/29 12:20
*/

public abstract class Print {
public abstract void printWeak();
public abstract void printStrong();
}

Banner类无变化

package adapter;

/**
* Copyright (C), 2014-2018, maoxiaomeng.com
* FileName: Banner
* Author: lihui
* Date: 2018/4/29 12:18
*/

public class Banner {
private String string;
public Banner(String string) {
this.string = string;
}

public void showWithParen() {
System.out.println("(" + string + ")");
}

public void showWithAster() {
System.out.println("*" + string + "*");
}
}

PrintBanner类的字段banner保存Banner类实例,printWeak和printStrong通过banner字段调用Banner类的showWithXX方法

package adapter;

/**
* Copyright (C), 2014-2018, maoxiaomeng.com
* FileName: PrintBanner
* Author: lihui
* Date: 2018/4/29 12:20
*/

public class PrintBanner extends Print {
private Banner banner;
public PrintBanner(String string) {
this.banner = new Banner(string);
}

public void printWeak() {
banner.showWithParen();
}

public void printStrong() {
banner.showWithAster();
}
}

之前是继承了Banner,直接调用其成员方法,此时通过字段来调用者两个方法;所以委托相当于,当PrintBanner的printWeak方法被调用,并不是PrintBanner类自己处理,而是委托交给了Banner实例的showWithParen方法来处理

 

Adapter模式里的角色:

Target(对象):负责定义所需要的方法;比如直流电,比如上面例子中的Print接口或者Print类

Client(请求者):负责使用Target角色所定义的方法进行具体处理;比如要用到直流电的电脑,比如上面例子中的Main类

Adaptee(被适配):持有既定方法的角色;比如交流电,比如上面例子中的Banner类

Adapter(适配):负责使用Adaptee角色的方法来满足Target角色的需求;比如将交流电转换成直流电,上面例子中的PrintBanner类

在类适配器模式中,Adapter角色通过集成来使用Adaptee角色;在对象适配器模式中,Adapter角色通过委托来使用Adaptee角色

很多时候,并非从0开始编码,有很多类已经经过充分测试和使用当中,那么假如将这些类重复利用的话,可以通过Adapter模式对现有的类进行适配,生成新的类

发表评论