适配器模式

在設計模式中，适配器模式（），有时候也称为包装器（），它将一个类的接口轉接成客户所预期的接口。适配器使得因接口不兼容而不能在一起工作的类能在一起工作，做法是将要被适配的已存在的类实例或接口，包裹在预期的目标接口的实现之中。

概述
適配器模式是著名的《設計模式：可復用物件導向軟體的基礎》所收錄的二十三個模式之一。此書描述了如何解決常見的設計問题，以設計出彈性且異重用的物件導向软件（亦即更容易實現、更改、测试、维护和重用的物件）。

 结构 

在上面的UML类图中，client类要求target接口，而不可以直接重复使用adaptee类，因为它的接口不符合target接口。client转而合作于adapter类，它依据adaptee而实现了target接口：

 对象适配器object adapter实现target接口，总是通过在运行时委托给adaptee对象（adaptee.specificOperation()）。 
 类适配器class adapter实现target接口，总是通过在编译时继承自adaptee类（specificOperation()）。

 对象适配器模式 
在这种适配器模式中，适配器容纳一个它包裹的类的实例。在这种情况下，适配器会调用被包裹对象的实例。


 类适配器模式 
这种适配器模式使用多个多态接口，实现或者继承它预期的目标接口和事先存在的被适配接口二者。预期的目标接口典型的被创建为纯接口类，特别是在不支持类的多重继承的编程语言比如Java（JDK 1.8以前）之中。


示例

在下面的对象适配器模式例子中，模拟使用Micro USB接头的早期安卓手机充电器，在不更换的前提下，给使用Lightning接头的早期苹果手机充电。这里的交流适配器连带USB线缆组成的USB充电器是客户client，USB线缆所插入的手机USB接头是目标接口target，而手机使用的与它不适配的接头是被适配者adaptee，为了清晰性可以为适配器采用类名字[被适配者]To[目标接口]Adapter，比如这个例子中的适配器LightningToMicroUsbAdapter。适配器应当有一个构造子方法，具有一个adaptee类变量作为参数。这个参数将被传递给适配器的一个实例成员。在调用clientMethod的时候，它将访问到这个adaptee，从而允许访问所需求的adaptee的数据，并在这个数据上进行运算而生成想要的输出。

Java
下面是Java例子：
interface ILightningPhone {
    void recharge();
    void useLightning();
}

interface IMicroUsbPhone {
    void recharge();
    void useMicroUsb();
}

class Iphone implements ILightningPhone {
    private boolean connector;

    @Override
    public void useLightning() {
        connector = true;
        System.out.println("Lightning connected");
    }

    @Override
    public void recharge() {
        if (connector) {
            System.out.println("Recharge started");
            System.out.println("Recharge finished");
        } else {
            System.out.println("Connect Lightning first");
        }
    }
}

class Android implements IMicroUsbPhone {
    private boolean connector;

    @Override
    public void useMicroUsb() {
        connector = true;
        System.out.println("MicroUsb connected");
    }

    @Override
    public void recharge() {
        if (connector) {
            System.out.println("Recharge started");
            System.out.println("Recharge finished");
        } else {
            System.out.println("Connect MicroUsb first");
        }
    }
}
/* exposing the target interface while wrapping source object */
class LightningToMicroUsbAdapter implements IMicroUsbPhone {
    private final ILightningPhone lightningPhone;

    public LightningToMicroUsbAdapter(ILightningPhone lightningPhone) {
        this.lightningPhone = lightningPhone;
    }

    @Override
    public void useMicroUsb() {
        System.out.println("MicroUsb connected");
        lightningPhone.useLightning();
    }

    @Override
    public void recharge() {
        lightningPhone.recharge();
    }
}

public class AdapterDemo {
    static void rechargeMicroUsbPhone(IMicroUsbPhone phone) {
        phone.useMicroUsb();
        phone.recharge();
    }

    static void rechargeLightningPhone(ILightningPhone phone) {
        phone.useLightning();
        phone.recharge();
    }

    public static void main(String[] args) {
        Android android = new Android();
        Iphone iPhone = new Iphone();

        System.out.println("Recharging android with MicroUsb");
        rechargeMicroUsbPhone(android);

        System.out.println("Recharging iPhone with Lightning");
        rechargeLightningPhone(iPhone);

        System.out.println("Recharging iPhone with MicroUsb");
        rechargeMicroUsbPhone(new LightningToMicroUsbAdapter (iPhone));
    }
}

输出： 
Recharging android with MicroUsb
MicroUsb connected
Recharge started
Recharge finished
Recharging iPhone with Lightning
Lightning connected
Recharge started
Recharge finished
Recharging iPhone with MicroUsb
MicroUsb connected
Lightning connected
Recharge started
Recharge finished

 C# 
下面是C#例子：
public interface ILightningPhone {
	void ConnectLightning();
	void Recharge();
}

public interface IUsbPhone {
	void ConnectUsb();
	void Recharge();
}

public sealed class AndroidPhone : IUsbPhone {
	private bool isConnected;

	public void ConnectUsb() {
		this.isConnected = true;
		Console.WriteLine("Android phone connected.");
	}

	public void Recharge() {
		if (this.isConnected) {
			Console.WriteLine("Android phone recharging.");
		}
		else {
			Console.WriteLine("Connect the USB cable first.");
		}
	}
}

public sealed class ApplePhone : ILightningPhone {
	private bool isConnected;

	public void ConnectLightning() {
		this.isConnected = true;
		Console.WriteLine("Apple phone connected.");
	}

	public void Recharge() {
		if (this.isConnected) {
			Console.WriteLine("Apple phone recharging.");
		}
		else {
			Console.WriteLine("Connect the Lightning cable first.");
		}
	}
}

public sealed class LightningToUsbAdapter : IUsbPhone {
	private readonly ILightningPhone lightningPhone;

	private bool isConnected;

	public LightningToUsbAdapter(ILightningPhone lightningPhone) {
		this.lightningPhone = lightningPhone;
	}

	public void ConnectUsb() {
		this.lightningPhone.ConnectLightning();
	}

	public void Recharge() {
		this.lightningPhone.Recharge();
	}
}

public void Main() {
	ILightningPhone applePhone = new ApplePhone();
	IUsbPhone adapterCable = new LightningToUsbAdapter(applePhone);
	adapterCable.ConnectUsb();
	adapterCable.Recharge();
}

输出：
Apple phone connected.
Apple phone recharging.

Python
下面是Python例子：
from abc import ABCMeta, abstractmethod

connected_prompt = "{} connected."
connected_first_prompt = "Connect {} first."
recharge_prompt = ["Recharge started.", "Recharge finished."]

class MicroUsbPhone(metaclass=ABCMeta):
    @abstractmethod
    def recharge(self): pass
    @abstractmethod
    def use_micro_usb(self): pass

class LightningPhone(metaclass=ABCMeta):
    @abstractmethod
    def recharge(self): pass
    @abstractmethod
    def use_lightning(self): pass

class Android(MicroUsbPhone):
    def __init__(self):
        self.connector = "MicroUSB"
        self.connected = False
    def use_micro_usb(self):
        self.connected = True
        print(connected_prompt.format(self.connector))
    def recharge(self):
        if self.connected:
            for state in recharge_prompt:
                print(state)
        else:
            print(connected_first_prompt.format(self.connector))

class IPhone(LightningPhone):
    def __init__(self):
        self.connector = "Lightning"
        self.connected = False
    def use_lightning(self):
        self.connected = True
        print(connected_prompt.format(self.connector))
    def recharge(self):
        if self.connected:
            for state in recharge_prompt:
                print(state)
        else:
            print(connected_first_prompt.format(self.connector))

class LightningToMicroUsbAdapter(MicroUsbPhone):
    def __init__(self, phone):
        assert isinstance(phone, LightningPhone)
        self.connector = "MicroUSB"
        self.connected = False
        self.adaptee = phone
    def use_micro_usb(self):
        self.connected = True
        print(connected_prompt.format(self.connector))
        self.adaptee.use_lightning()
    def recharge(self):
        if self.connected:
            self.adaptee.recharge()
        else:
            print(connected_first_prompt.format(self.connector))

def micro_usb_recharger(phone):
    assert isinstance(phone, MicroUsbPhone)
    phone.use_micro_usb()
    phone.recharge()

def lightning_recharger(phone):
    assert isinstance(phone, LightningPhone)
    phone.use_lightning()
    phone.recharge()

def demo():
    android = Android()
    iphone = IPhone()
    print("Recharging Android with MicroUSB recharger.")
    micro_usb_recharger(android)
    print()
    print("Recharging iPhone with Lightning recharger.")
    lightning_recharger(iphone)
    print()
    print("Recharging iPhone with MicroUSB recharger.")
    micro_usb_recharger(LightningToMicroUsbAdapter(iphone))
其执行：
>>> demo()
Recharging Android with MicroUSB recharger.
MicroUSB connected.
Recharge started.
Recharge finished.

Recharging iPhone with Lightning recharger.
Lightning connected.
Recharge started.
Recharge finished.

Recharging iPhone with MicroUSB recharger.
MicroUSB connected.
Lightning connected.
Recharge started.
Recharge finished.

参见
代理模式
修饰模式

引用

Category:軟體設計模式