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

利津杜拉伊拉伊

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

两路适配器

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

更新1

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

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

现在,在这种情况下我怎么可以把它作为一个双向适配器。双向适配器地址在其他使用两个系统,其中一个系统的特点有问题,反之亦然。适配器类设置为同时吸收的重要的共同方法,并提供适应于这两者。产生的适配器对象对双方都是可接受的

加布里埃尔·皇后

C#3.0设计模式中提取的所有引号恰好与您问题的出处相同。
报价单上的粗体emphasys在我身上。

在双向适配器上:

适配器提供对Adaptee中某些行为的访问(ITarget接口中要求的行为),但是Adapter对象不能与Adaptee对象互换。不能在Adaptee对象可以使用的地方使用它们,因为它们在Adaptee的实现上而不是在其接口上起作用。有时候,我们需要有对象可以透明ITarget或适配者的物体如果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接口可以不同。适配器必须能够处理名称更改。在以前的适配器版本中,所有Adaptee方法都是如此,但是客户端必须在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共享作出适配者提供给客户的相同objetive,每一个提供了一组不同的问题的解决方案,无论是双向适配器使两个目标可适配者,反之亦然或所述可插拔抽象以原子方式两种靶和适配者的行为

希望这有助于清除两个适配器之间的差异。

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

我可以用你的例子告诉你没有得到的双向适配器的目的。仅当您需要同时使用Adaptee和Target时,才需要它,就像您将它们的不同功能合并到一个对象中一样。
如果它们都执行相同的操作(即Ride),则最好改用可插拔适配器。

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

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章