C#中的双向适配器和可插拔适配器模式有什么区别? [英] What is the difference between Two-way Adapter and Pluggable Adapter Pattern in C#?

查看:65
本文介绍了C#中的双向适配器和可插拔适配器模式有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

双向适配器和可插拔适配器都可以访问这两个类,并且还可以更改需要更改的方法的行为.以下是我的代码:

Both Two-way Adapter and Pluggable Adapter can access both the classes and also change the behavior of the method which is required to be changed. The following is my code:

双向适配器

public interface IAircraft
{
    bool Airborne { get; }
    void TakeOff();
    int Height { get; }
}

// Target
public sealed class Aircraft : IAircraft
{
    int height;
    bool airborne;
    public Aircraft()
    {
        height = 0;
        airborne = false;
    }
    public void TakeOff()
    {
        Console.WriteLine("Aircraft engine takeoff");
        airborne = true;
        height = 200; // Meters
    }
    public bool Airborne
    {
        get { return airborne; }
    }
    public int Height
    {
        get { return height; }
    }
}
// Adaptee interface
public interface ISeacraft
{
    int Speed { get; }
    void IncreaseRevs();
}
// Adaptee implementation
public class Seacraft : ISeacraft
{
    int speed = 0;
    public virtual void IncreaseRevs()
    {
        speed += 10;
        Console.WriteLine("Seacraft engine increases revs to " + speed + " knots");
    }
    public int Speed
    {
        get { return speed; }
    }
}
// Adapter
public class Seabird : Seacraft, IAircraft
{
    int height = 0;
    // A two-way adapter hides and routes the Target's methods
    // Use Seacraft instructions to implement this one
    public void TakeOff()
    {
        while (!Airborne)
            IncreaseRevs();
    }
    // Routes this straight back to the Aircraft
    public int Height
    {
        get { return height; }
    }

    // This method is common to both Target and Adaptee
    public override void IncreaseRevs()
    {
        base.IncreaseRevs();
        if (Speed > 40)
            height += 100;
    }
    public bool Airborne
    {
        get { return height > 50; }
    }
}
class Experiment_MakeSeaBirdFly
{
    static void Main()
    {
        // No adapter
        Console.WriteLine("Experiment 1: test the aircraft engine");
        IAircraft aircraft = new Aircraft();
        aircraft.TakeOff();
        if (aircraft.Airborne) Console.WriteLine(
        "The aircraft engine is fine, flying at "
        + aircraft.Height + "meters");
        // Classic usage of an adapter
        Console.WriteLine("\nExperiment 2: Use the engine in the Seabird");
        IAircraft seabird = new Seabird();
        seabird.TakeOff(); // And automatically increases speed
        Console.WriteLine("The Seabird took off");
        // Two-way adapter: using seacraft instructions on an IAircraft object
        // (where they are not in the IAircraft interface)
        Console.WriteLine("\nExperiment 3: Increase the speed of the Seabird:");
        (seabird as ISeacraft).IncreaseRevs();
        (seabird as ISeacraft).IncreaseRevs();
        if (seabird.Airborne)
            Console.WriteLine("Seabird flying at height " + seabird.Height +
            " meters and speed " + (seabird as ISeacraft).Speed + " knots");
        Console.WriteLine("Experiments successful; the Seabird flies!");

        Console.Read();
    }
}

可插入模式

class Adaptee
{
    public double Precise(double a, double b)
    {
        return a / b;
    }
}

// New standard for requests
class Target
{
    public string Estimate(int i)
    {
        return "Estimate is " + (int)Math.Round(i / 3.0);
    }
}    

// Implementing new requests via old
class Adapter : Adaptee
{
    public Func<int, string> Request;    
    // Different constructors for the expected targets/adaptees    
    // Adapter-Adaptee
    public Adapter(Adaptee adaptee)
    {
        // Set the delegate to the new standard
        Request = x =>
        {
            return "Estimate based on precision is " +
           (int)Math.Round(Precise(x, 3));
        };
    }

    // Adapter-Target
    public Adapter(Target target)
    {
        // Set the delegate to the existing standard
        Request = target.Estimate;
    }
}

class Client
{    
    static void Main()
    {    
        Adapter adapter1 = new Adapter(new Adaptee());
        Console.WriteLine(adapter1.Request(5));

        Adapter adapter2 = new Adapter(new Target());
        Console.WriteLine(adapter2.Request(5));    
        Console.Read();

    }
}

在上面的两个代码示例中,我没有发现关于模式功能的任何不同.那么这些模式之间有什么区别?谁能帮助我理解它?我一直在参考设计模式C#3.0

In the above two code samples, I don't find anything different in respect of the patterns' functionality. So what is the difference between the patterns? Can anyone help me understand it? I have been refering to this Design Pattern C# 3.0

更新1

我无法理解本文中给出的示例,因此我更新了一个简单的代码,并且我想基于该代码从scenaerio实现双向适配器

I couldnt understand the example given in this refrence, so i have updated a simple code, and i want to implement Two-Way adapter from the scenaerio based on the code

 interface Ibike {
        void Ride(int energy,int time);
    }
    class Bike : Ibike {
        public void Ride(int energy,int time) {
            Console.WriteLine("riding bike with calories of energy "+energy+" spend time "+time);
        }
    }
    interface Imotorcycle {
        void Ride(int fuel);
    }
    class Motorcycle : Imotorcycle {
        public void Ride(int fuel) {
            Console.WriteLine("riding motorbike with fuel "+fuel);
        }
    }
    class Client {
        static void Main() {
            Ibike bike = new Bike();
            Imotorcycle motorBike = new Motorcycle();
            bike.Ride(50, 2);
            motorBike.Ride(3);


            Console.Read();
        }
    }

现在在这种情况下,如何使它成为双向适配器.双向适配器解决了两个系统的问题,其中一个系统的特性必须在另一个系统中使用,反之反之亦然.设置了一个Adapter类来吸收重要的共同点并提供两种方法的改编.所结果的适配器对象对双方都是可接受的

Now in this scenario how can i make it as a Two-way 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

推荐答案

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

这篇关于C#中的双向适配器和可插拔适配器模式有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆