25 Nisan 2020 Cumartesi

GoF - Adapter Örüntüsü - Two Way Adapter

Two Way Adapter
Class Adapter örneğinde Adapter sınıfımız sadece Target nesnesi gibi davranabiliyordu. Ancak bazen Adapter nesnesinin hem Target hem de Adaptee gibi davranması gerekebilir. Açıklaması şöyle
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 interfaces; however, such multiple inheritance is not possible in C#, so we must look at other solutions.

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.
Örnek
Elimizde bir hem Target arayüzü hem de Adaptee arayüzleri ve bunların gerçekleştirimleri olsun
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"); 
  }        
}
Kullanmak için şöyle yaparız.
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();
Örnek
Elimizde bir Target arayüzü ve gerçekleştirimi olsun.
public interface IAircraft
{
  bool Airborne { get; }
  void TakeOff();
  int Height { get; }
}

// Target
public sealed class Aircraft : IAircraft
{
  
  public void TakeOff()
  {
    ...
  }
  public bool Airborne
  {
    ...
  }
  public int Height
  {
    ...
  }
}
Elimizde bir Adaptee arayüzü ve gerçekleştirimi olsun.
// Adaptee interface
public interface ISeacraft
{
    int Speed { get; }
    void IncreaseRevs();
}
// Adaptee implementation
public class Seacraft : ISeacraft
{
  public virtual void IncreaseRevs()
  {
    ...
  }
  public int Speed
  {
    ...
  }
}
Adapter sınıfımız yine Adaptee sınıfından kalıtır ve Target arayüzünü gerçekleştirir. Şöyle yaparız. Burada farklı olarak Adaptee sınıfının IncreaseRevs() metodunu da override ederek davranışı değiştirir.
// 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; }
    }
}
Kullanmak için şöyle yaparız.
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)

(seabird as ISeacraft).IncreaseRevs();
(seabird as ISeacraft).IncreaseRevs();

Hiç yorum yok:

Yorum Gönder