且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

C#中的双向适配器和可插拔适配器模式有什么区别?

更新时间:2023-08-27 16:36:46

All quotes extracted from the C# 3.0 Design Patterns, which happens to be same source of your question.
Bold emphasys on the quotatios are on me.

在双向适配器上:

适配器提供对Adaptee中某些行为(行为在ITarget接口中是必需的),但适配器对象不是可与Adaptee对象互换.它们不能在哪里使用Adaptee对象之所以可以这样,是因为它们致力于实现Adaptee,而不是它的界面.有时我们需要具有可以是透明的ITarget或Adaptee对象.这可能很容易如果Adapter从两个类都继承,则实现;然而,这样的多重继承在C#中是不可能的,所以我们必须看一下其他解决方案.

Adapters provide access to some behavior in the Adaptee (the behavior required in the ITarget interface), but Adapter objects are not interchangeable with Adaptee objects. They cannot be used where Adaptee objects can because they work on the implementation of the Adaptee, not its interface. Sometimes we need to have objects that can be transparently ITarget or Adaptee objects. This could be easily achieved if the Adapter inherited both from both classes; however, such multiple inheritance is not possible in C#, so we must look at other solutions.

双向适配器解决了两个问题必须在其中使用一个系统的特征的系统其他,反之亦然.设置了一个Adapter类来吸收两者的重要共同方法,并为两者提供改编.由此产生的适配器对象对双方都是可接受的.从理论上讲,这个想法可以扩展到两个以上的系统,因此我们可以有多路适配器,但是有一些实现局限性:没有多重继承,我们必须插入一个每个原始类和适配器之间的接口.

The two-way adapter addresses the problem of two systems where the characteristics of one system have to be used in the other, and vice versa. An Adapter class is set up to absorb the important common methods of both and to provide adaptations to both. The resulting adapter objects will be acceptable to both sides. Theoretically, this idea can be extended to more than two systems, so we can have multiway adapters, but there are some implementation limitations: without multiple inheritance, we have to insert an interface between each original class and the adapter.

在这种情况下,除了要在多个系统之间适应通用功能之外,我们还讨论了使来自不同系统的两个(或多个)不同功能可用于同一适配器上的调用.在您的代码示例中:

In this case, on top of adapting common functionality between multiple systems, we are talking about making two (or more) distinct functionalities from distinct systems available for the calling on the same adapter. In your code sample:

//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接口中的方法可以不同.适配器必须能够处理名称更改.在以前的适配器版本中,对于所有Adaptee都是如此.方法,但客户端必须在ITarget界面中使用名称.(...)

可插拔适配器可以从中筛选出要插入哪个对象时间.插入服务及其方法后,分配给委托对象后,关联会持续到另一个分配了一组方法.可插拔适配器的特征是它会为它适应的每种类型都有构造函数.在它们的每一个中,它都进行委托分配(一个或多个)一种,如果还有其他方法可以重新路由.

The pluggable adapter sorts out which object is being plugged in at the time. Once a service has been plugged in and its methods have been assigned to the delegate objects, the association lasts until another set of methods is assigned. What characterizes a pluggable adapter is that it will have constructors for each of the types that it adapts. In each of them, it does the delegate assignments (one, or more than one if there are further methods for rerouting).

因此,在这里我们有一个通用名称,可以通过该通用名称调用任何系统的任何插入方法,但在给定时间只能使用一个.我猜想这两种方法都可以通过不同的方式或以不同的细节级别执行可提供相似结果的操作,但这似乎并不是该模式的规则.

So here we have a common name by which any plugged method of any system could by called, but only one can be used at a given time. I supose it would be expected that both methods perform operations that delivers similar results through different means or with distinct detail levels, but that does not seem to be a rule for the pattern.

再次使用您的示例:

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向客户提供Adaptee的相同目标,但每个适配器都提供了针对不同问题的解决方案,无论是双向适配器使得两个Target都可用于Adaptee,反之亦然可插拔的,以原子方式抽象化Target和Adaptee的行为.

Even though all adapters share the same objetive of making a Adaptee available to a Client through a ITarget, each one offers a solution for a different set of problems, be it the Two-way adapter making both Target available to Adaptee and vice-versa or the Pluggable abstracting the behavior of both Target and Adaptee in an atomic manner.

希望能帮助清除两个适配器之间的差异.

Hope that helps clearing out the difference between the two adapters.

更新1.有关双向的更多信息:

我可以通过您的示例来说明您没有达到双向适配器的目的.仅当您需要同时使用Adaptee和Target时才需要它,就像您将其独特的功能合并到一个对象中一样.
如果它们都执行相同的操作(即Ride),则***改用可插拔适配器.

I can tell by your example that you did not get the purpose of the Two-way adapter. It is required only when you need to use both the Adaptee and the Target interchangeably, as if you were merging their distinct functionalities into a single object.
If they both do the same thing (that is, Ride), you would be better off using a Pluggable Adapter instead.

让我们以一种使用双向适配器有意义的方式来修改您的新样本.

Let's revamp your new sample in a way that it makes sense to use a Two-way adapter.

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();
    }
}