所有引言均摘自C# 3.0 设计模式 https://msdn.microsoft.com/en-us/library/orm-9780596527730-01-04.aspx,这恰好是您问题的同一来源。
大胆强调引文是我的。
在双向适配器上:
适配器提供对适应者中某些行为的访问(行为
ITarget 接口中需要),但 Adapter 对象不是
可与 Adaptee 对象互换。它们不能用于以下地方
Adaptee 对象可以,因为它们致力于实现
适应者,而不是它的接口。有时我们需要有一些对象可以
是透明的 ITarget 或 Adaptee 对象。这很容易
如果 Adapter 继承了这两个类,则可以实现;然而,
这种多重继承在 C# 中是不可能的,所以我们必须看看
其他解决方案。
双向适配器解决了两个问题
系统,其中必须利用一个系统的特性
其他,反之亦然。设置一个Adapter类来吸收
两者的重要共同方法,并为两者提供适应。
生成的适配器对象将被双方接受。理论上,这个想法可以扩展到两个以上的系统,所以
我们可以有多路适配器,但有一些实现
限制:如果没有多重继承,我们必须插入一个
每个原始类和适配器之间的接口。
在这种情况下,除了调整多个系统之间的通用功能之外,我们还讨论使来自不同系统的两个(或更多)不同功能可用于在同一适配器上进行调用。在您的代码示例中:
//The adapter
IAircraft seabird = new Seabird( );
// This is a IAircraft method
seabird.TakeOff( );
//This is NOT a IAircraft method, but is made available through the adapter.
(seabird as ISeacraft).IncreaseRevs( );
现在,在可插拔适配器上:
可插拔适配器的一个显着特征是
客户端调用的方法以及ITarget接口中存在的方法
可以不同。适配器必须能够处理名称更改。
在以前的适配器变体中,这对于所有适配器都是如此
方法,但客户端必须使用 ITarget 接口中的名称。 (...)
可插式适配器会分出哪个对象正在插入
时间。一旦服务被插入并且它的方法已经被
分配给委托对象,关联持续到另一个
分配了一组方法。可插拔适配器的特点是
它将为它所适应的每种类型都有构造函数。
在每一个中,它都会执行委托分配(一个或多个
如果还有其他重新路由的方法,则为一个)。
因此,这里我们有一个通用名称,可以通过该名称调用任何系统的任何插入方法,但在给定时间只能使用一个。
我认为这两种方法都会执行通过不同方式或具有不同细节级别提供相似结果的操作,但这似乎不是该模式的规则。
再次,使用您的示例:
Adapter adapter1 = new Adapter (new Adaptee( ));
//Here, it will call the Adaptee's abstracted method.
adapter1.Request(5);
//The only way to call the Target's method is to instantiate a new adapter with the target
Adapter adapter2 = new Adapter (new Target( ));
Console.WriteLine(adapter2.Request(5));
结论:
尽管所有适配器都具有通过 ITarget 使适配器可供客户端使用的相同目标,但每个适配器都针对不同的问题集提供了解决方案,无论是双向适配器使目标对适应者可用,反之亦然 or the 可插拔以原子方式抽象目标和适应者的行为.
希望这有助于消除两个适配器之间的差异。
更新 1. 有关双向的更多信息:
我可以从你的例子看出你没有明白双向适配器的目的。仅当您需要互换使用适应者和目标时才需要它,就好像您将它们不同的功能合并到单个对象中一样。
如果它们都做同样的事情(即骑行),那么您最好使用可插拔适配器。
让我们以一种使用双向适配器有意义的方式修改您的新示例。
interface IBike {
void Pedal();
}
class Bike : IBike {
public void Pedal() {
Console.WriteLine("Moving my vehicle with my body");
}
}
interface IMotorcycle {
void Accelerate();
}
class Motorcycle : IMotorcycle {
public virtual void Accelerate() {
Console.WriteLine("Moving my vehicle with a hydrocarbon fuel engine");
}
}
class ElectricBike : Motorcycle, IBike {
bool _isAccelerating = false;
public override void Accelerate() {
_isAccelerating = true;
Console.WriteLine("Moving my vehicle with a electric engine");
}
public void Pedal() {
if (!_isAccelerating)
Console.WriteLine("Moving my vehicle with my body");
else
Console.WriteLine("Occupying my body with senseless effort, for my vehicle is already moving");
}
}
class MovingMyVehicle {
static void Main() {
IMotorcycle motorBike = new Motorcycle();
//That is expected, as IMotorcycle can Accelerate.
motorBike.Accelerate();
IBike newBike = new ElectricBike();
//That too is expected, as IBike can Pedal.
newBike.Pedal();
//Now that´s something new, as IBike cannot Accelerate,
//but the the ElectricBike adapter can, as it implements both interfaces.
(newBike as IMotorcycle).Accelerate();
Console.Read();
}
}