definition
Adapter design pattern, by definition is the role of the adapter becomes organized way of summary abstract code, existing code by adapting the adapter, in order to meet the requirements of the project to another class or interface. In other words, a class interface adapter (packaging / converting) into another interface clients (the caller) desired. Adapter design pattern has the following two forms:
- Class Adapter mode (inherited adapter)
- Object Adapter mode (using a delegate adapter)
Issues into
We used laptop accessories have one adapter, is responsible for 220V
the alternating current is converted into 12V
DC power for laptops, it exists role is to 220V
alternating current is converted into 12V
direct current. So it is the adapter, 220V
AC power adapter is to be the object, and 12V
the direct current is converted target object, the caller laptop is the target object.
Application Adapter design patterns in the JDK source code
Learn adapter design pattern, of course, from the need JDK
to find traces of it in the JDK
source code, where the use of the adapter design pattern of many, such as the most common IO
conversion flow and collections and so on. Next we together from source code to analyze how to use the adapter design pattern is up.
Together we read the java.io.InputStreamReader(InputStream)
part of the source code:
InputStreamReader
The role of the byte stream into a character stream, the conversion between them is a bridge (adapter), that is to say, InputStreamReader
is the adapter, is responsible for InputStream
convert Reader
, so that you can use Reader
methods to perform the operation.
package java.io;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import sun.nio.cs.StreamDecoder;
public class InputStreamReader extends Reader {
private final StreamDecoder sd;
public InputStreamReader(InputStream in) {
super(in);
try {
sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
} catch (UnsupportedEncodingException e) {
throw new Error(e);
}
}
public String getEncoding() {
return sd.getEncoding();
}
public int read() throws IOException {
return sd.read();
}
public int read(char cbuf[], int offset, int length) throws IOException {
return sd.read(cbuf, offset, length);
}
public boolean ready() throws IOException {
return sd.ready();
}
public void close() throws IOException {
sd.close();
}
}
The above code is the result of the deletion of part of the code, delete the comments in the source code as well as several construction methods, read from the source point of view, this form of adapter design pattern uses " 对象适配器模式
" As for what is " 对象适配器模式
," we will in the latter study in the introduction, readers can temporarily disregard what is' 对象适配器模式
. "
Manual mode adapter is designed to achieve
Next, we will implement two adapter design manual mode, with a simple code to illustrate how the adapter design pattern is up and running.
Former child have played QQ
the game, sometimes need to recharge Q
coins, use Q
coins to purchase items in the game, this scenario can be fully applicable adapter design mode, in this scenario, using the Q
money to buy game items are our needs, but also is our goal ( Target
), but the status quo is that we now have the RMB, the yuan is adapted object ( Adaptee
), the RMB can not directly buy props in the game, it needs to be converted into the Q
currency can be traded, so we also need an adapter ( Adapter
), is responsible for converting the yuan into Q
dollars.
According to the above text, we can be summarized into a table, you can easily clear the relationship between geography:
Roles | Actor | effect |
---|---|---|
Target | Props to buy the game interface | There recharge Q coins interfaces have to use Q coins prepaid game props Interface |
Adapter | Q currency recharge device | RMB will be converted into Q coins and complete recharge |
Adaptee | Renminbi | Adapted, the object is converted |
According to the above relationship, we were to create a class or interface corresponding to each role. Here we simulate the use of the yuan prepaid Q
currency, using the Q
case of currency to buy game items, assuming a unit of the yuan can recharge 10
two Q
coins, each Q
coin can be a game props.
Code Example 1: Class Adapter design pattern (using inheritance adapter)
- Target
Our goal is to have an interface, this interface can purchase game items, but need to use the Q
money to make a purchase. In the adapter design pattern, it is the ultimate goal we needed.
package cn.itlemon.design.pattern.chapter02.adapter.example3;
/**
* @author jiangpingping
* @date 2018/9/6 下午7:43
*/
public interface TargetInterface {
/**
* 购买qCoinCount个游戏道具
*/
void buyGameProps();
}
- Adaptee
Now is the status quo of RMB on hand, so the need for a Q
currency recharge device, the value of the RMB into the same Q
currency. Adapter design pattern in which the yuan is needed to be adapted to the object because it can not be directly used to purchase game items, but that it must pass before it can recharge Q
currency, in order to meet the requirements.
package cn.itlemon.design.pattern.chapter02.adapter.example3;
/**
* 人民币
*
* @author jiangpingping
* @date 2018/9/6 下午7:45
*/
public class Rmb {
private int count;
public Rmb(int count) {
this.count = count;
}
public int getCount() {
return this.count;
}
}
- Adapter
So we need a Q
currency recharge device, the RMB into Q
dollars, and then also have to buy the game props function. In the adapter design pattern, the Q
currency recharge is that we need an adapter.
package cn.itlemon.design.pattern.chapter02.adapter.example3;
/**
* Q币充值器
*
* @author jiangpingping
* @date 2018/9/6 下午7:31
*/
public class QCoinRechargeableDevice extends Rmb implements TargetInterface {
private int qCoinCount;
public QCoinRechargeableDevice(int rmbCount) {
super(rmbCount);
this.qCoinCount = getCount() * 10;
}
@Override
public void buyGameProps() {
System.out.println("一共购买了" + qCoinCount + "个道具");
}
}
- Main
Here to write a Main
method to validate our design above adapter design pattern, the main code is as follows:
package cn.itlemon.design.pattern.chapter02.adapter.example3;
/**
* @author jiangpingping
* @date 2018/9/6 下午9:26
*/
public class Main {
public static void main(String[] args) {
TargetInterface qCoinRechargeableDevice = new QCoinRechargeableDevice(10);
qCoinRechargeableDevice.buyGameProps();
}
}
Here, we have to Q
recharge currency recharge device 10
units of the RMB, you can complete the purchase 100
game props change. Originally RMB can not be directly used to purchase game items, after using the adapter design pattern, you can purchase game items to complete our needs.
Use inherited adapter UML class diagram
Use inherited adapters have a feature that is Adapter
inherited Adaptee
, and realized Target
that this is the relationship between the three.
Code Example 2: Object Adapter design pattern (using the delegate adapter)
Here only the code posted, for each class described in the above have been described.
- Target
package cn.itlemon.design.pattern.chapter02.adapter.example4;
/**
* @author jiangpingping
* @date 2018/9/10 下午9:16
*/
public abstract class TargetInterface {
/**
* 购买qCoinCount个游戏道具
*/
public abstract void buyGameProps();
}
- Adaptee
package cn.itlemon.design.pattern.chapter02.adapter.example4;
/**
* 人民币
*
* @author jiangpingping
* @date 2018/9/6 下午7:45
*/
public class Rmb {
private int count;
public Rmb(int count) {
this.count = count;
}
public int getCount() {
return this.count;
}
}
- Adapter
package cn.itlemon.design.pattern.chapter02.adapter.example4;
/**
* @author jiangpingping
* @date 2018/9/10 下午9:18
*/
public class QCoinRechargeableDevice extends TargetInterface {
private Rmb rmb;
public QCoinRechargeableDevice(Rmb rmb) {
this.rmb = rmb;
}
@Override
public void buyGameProps() {
System.out.println("一共购买了" + rmb.getCount() * 10 + "个道具");
}
}
- Main
package cn.itlemon.design.pattern.chapter02.adapter.example4;
/**
* @author jiangpingping
* @date 2018/9/10 下午9:16
*/
public class Main {
public static void main(String[] args) {
TargetInterface qCoinRechargeableDevice = new QCoinRechargeableDevice(new Rmb(10));
qCoinRechargeableDevice.buyGameProps();
}
}
Use delegate (object) adapter UML class diagram
Use commissioned adapters have a feature that is Adapter
owned Adaptee
and inherited Target
abstract class, which is the relationship between the three.
On the adapter mode key role
One adapter design pattern is a more common design patterns, now on the adapter design pattern analysis roles.
-
Target(对象)
该角色负责定义最终的需求,也就是使用适配器模式之后的最终效果。在本次示例中,TargetInterface
就是扮演了这个Target
角色。 -
Adaptee(被适配)
该角色定义的是原始的功能,它也许无法直接被利用,但是又不能随意更改,所以它就需要被适配,使得在不修改原始代码的情况下能激活Target
的功能。在本次示例中,Rmb
扮演了这个角色。 -
Adapter(适配)
该角色是适配器设计模式的核心角色,他负责适配Adaptee
和Target
,使得Adaptee
来满足Target
的需求。在本次示例中,QCoinRechargeableDevice
扮演了这个角色。 -
Client(请求者)
该角色负责调用Target
的方法来进行一系列的逻辑处理。在本次示例中,Main
类扮演了这个角色。
适配器设计模式UML类图
分析完适配器设计模式的重要角色,当然也得理清适配器设计模式的UML
类图。
- 使用继承的适配器设计模式类图
- 使用委托的适配器设计模式类图
为什么要使用适配器设计模式
我们往往有这种思想,要使用什么类的方法,直接使用不就OK
了,或者稍微修改一下已有的代码不就可以使用了吗?其实这种思想是不正确的,因为在现有类的基础下,很多类的方法都经过了严格的测试,贸然地去修改他容易造成意外情况的发生,我们使用适配器设计模式,往往无需修改现有的代码,直接在现有的代码的基础上创建新的代码,这样即使出了错误,我们也能很快从我们新写的代码中找出端倪。使用适配器设计模式,也是对现有代码的一种重复利用。
更多干货分享,欢迎关注我的微信公众号:爪哇论剑(微信号:itlemon)