---
tags: Structural Patterns
---
# 轉接器模式 Adapter
## 架構圖

### 角色
## 目的
1. 想利用現有的class,但它的介面卻與你所需要的不符。
2. 想做一個可再利用的class,且能與其他毫不相關、甚至尚未出現的class搭配使用,也就是說,想與介面未必相容的class合作無間。
3. 想用一些現有的sub-class,雖然介面不相容,但又不適合一個個再去衍生sub-class修改介面。Adapter可以幫忙轉換它們的super-class。
## 比較
### Class Adapter
* 綁死在實體adaptee類別上。
* 可以覆寫adaptee的某些行為。
* 只引入一個物件個體。
* 不能在Runtime時轉換adaptee的類別。
### Object Adapter
* 不會綁死在adaptee類別上。
* 可能會引入adaptee的子類別用以覆寫行為(但不是覆寫adaptee本身)。
* 引入多個物件個體。
* 可以在Runtime時轉換adaptee的類別。
* 可以透過衍生sub-adaptee子類別向adaptee增加新功能。
```java=
//Adaptee
public interface AdvancedMediaPlayer {
public void playVlc(String fileName);
public void playMp4(String fileName);
}
//Concrete Adaptee
public class VlcPlayer implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName) {
// TODO Auto-generated method stub
System.out.println("Playing vlc file. Name: "+ fileName);
}
@Override
public void playMp4(String fileName) {
// TODO Auto-generated method stub
}
}
//Concrete Adaptee
public class Mp4Player implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName) {
// TODO Auto-generated method stub
}
@Override
public void playMp4(String fileName) {
// TODO Auto-generated method stub
System.out.println("Playing mp4 file. Name: "+ fileName);
}
}
//Adapter
public class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
// TODO Auto-generated method stub
// inbuilt support to play mp3 music files
if (audioType.equalsIgnoreCase("mp3")) {
System.out.println("Playing mp3 file. Name: " + fileName);
}
// mediaAdapter is providing support to play other file formats
else if (audioType.equalsIgnoreCase("vlc") ||
audioType.equalsIgnoreCase("mp4")) {
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
}
else {
System.out.println("Invalid media. " + audioType + " format not supported");
}
}
}
```
In this following ex, use
* Duck as a target
* Turkey as a adaptee
* TurkeyAdator as a adaptor
suppose we r now need to pretend turkey as a duck,
then use TurkeyAdator
if the client want duck to quack(), it will call turkey gobble(),
if the client want duck to walk, it will call turkey fly()
client think that it's interact with the duck, but actually, there is a turkey behind the duck skin interact with the user :P
code:
``` java
// target
public interface Duck {
public void quack();
public void fly();
}
// concrete target
public class MallardDuck implements Duck {
@Override
public void quack()
{
System.out.println("Quack");
}
@Override
public void fly()
{
System.out.println("I'm flying");
}
}
// adaptee
public interface Turkey {
public void gobble();
public void fly();
}
// concrete adaptee
public class WildTurkey implements Turkey {
@Override
public void gobble()
{
System.out.println("Gobble gobble");
}
@Override
public void fly()
{
System.out.println("I'm flying a short distance");
}
}
// adaptor
public class TurkeyAdapter implements Duck {
private Turkey mTurkey;
public TurkeyAdapter(Turkey turkey)
{
mTurkey = turkey;
}
@Override
public void quack()
{
mTurkey.gobble();
}
@Override
public void fly()
{
mTurkey.fly();
}
}
```