**نموذج التصميم المحول** هو نموذج عبارة عن محول، يقوم بعمل واجهة لنظام معقد، ربما يكون كود جاهز مثلاً أو إحدى المكتبات القديمة لديك و تريد ان تعيد استخدامها و لكن الواجهة لهذا الكود أو المكتبة غير متوافق مع الكود الجديد الذي تستخدم معه هذه المكتبة فنقوم بعمل **محول** يوافق بين الجزئيتين  

ITarget :  

هو الواجهة المراد استخدامها من المستخدم النهائي للكود أو المستخدم لل**محول**  

Adaptee :  

هو الكود أو المكتبة والمراد استخدامه  

Adapter :  

هي الصف التي تورث من ITarget وتوافق شروط ال Adaptee  

Request:  

هو الطلب الذي نريد تنفيذه في النهاية  

SpecificRequest :  

المحتوى الذي نريد تنفيذه والموجود في ال Adaptee  

نستعرض مثال بسيط لتوضيح الفكرة

في البداية نعرض الصف Adaptee المراد الانتفاع من خدماتها و هي كود قديم أو ربما يكون كود حديث في نفس البرنامج و لكن نريد أن نستخدمه في مكان اخر لا يتوافق مع الواجهة له ونريد ان نستبدله

```
// Adapter Pattern - Simple Judith Bishop Oct 2007
// Simplest adapter using interfaces and inheritance

 Existing way requests are implemented
class Adaptee
{
 // Provide full precision
 public double SpecificRequest(double a, double b)
 {
 return a / b;
 }
}

```

هذا الواجهة الجديدة ITarget للكود الجديد الذي نريد ان نعمل عليه

```
// Required standard for requests
interface ITarget
{
 // Rough estimate required
 string Request(int i);
}

```

هنا نقوم بتعريف الصف Adapter تجمع بين القديم و الحديث و توفق بينهم حيث اني في الصف الجديد رغبتي هي أن اريد أن أمرر أي رقم فيقسم تلقائيا على 3 بدون أن أمرر الرقم 3 و هذا ما تقوم به الدالة Request تقوم باستخدام الدالة القديمة SpecificRequest وتمرر الرقم الجديد وتمرر الرقم 3 ونقوم أيضا بعمل تقريب للناتج إلى اقرب رقم صحيح

```
// Implementing the required standard via Adaptee
class Adapter : Adaptee, ITarget
{
 public string Request(int i)
 {
 return "Rough estimate is "+ (int)Math.Round(SpecificRequest(i, 3));
 }
}

```

الآن نقوم بعرض الصف Client ونرى الفرق بين الحديث والقديم

```
class Client
{
 static void Main()
 {
 // Showing the Adapteee in standalone mode
 Adaptee first = new Adaptee();
 Console.Write("Before the new standard\nPrecise reading: ");
 Console.WriteLine(first.SpecificRequest(5, 3));

 // What the client really wants
 ITarget second = new Adapter();
 Console.WriteLine("\nMoving to the new standard");
 Console.WriteLine(second.Request(5));
 }
}

```

ويكون الناتج كالتالي

```
/\* Output
42 Before the new standard
43 Precise reading: 1.66666666666667
44
45 Moving to the new standard
46 Rough estimate is 2
47 \*/

```

Two-Way Adapters
----------------

هناك مشكلة من الممكن ان نواجهها اثناء عملنا وهي إذا أردنا ذات مرة ان نقوم بعمليتين احداهما تابعة لمكتبة معينة والاخرى تتبع لمكتبة ثانية ونريد ان نجعلهما يعملان سويافمثلا لو ان مخترع حاول ان يصنع طائرة مائية لها هيكل طائرة وموتور ولوحة تحكم لسفينة واسماها Seabird ويقوم بتشغيل الطائرة AirCraft والجزء المائي منها اثناء وجدودها على صفحة الماء SeaCradt وسوف يتحكم في اختراعه عن طريق interface لكل جزء وسوف يكون الجزء المتحكم في الانتقال من الواجهة لاخر هو ال Seabird. اللآن نحول هذا المثال إلى كود برمجي

- في البداية نقوم بعمل الواجهة الذي سيكون مسئول عن مرحلة الطيران

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

```

كما نرى فهو يشمل على خاصية Airborne Property واخرى Height والدالة Takeoff
- الآن نقوم بتوريث الواجهة لصف يكون مسئول عن الطيران

```
// 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; }
 }
 }

```

الصف Aircraft كما نرى هي الصف sealed أي انه لا يمكن ان نشتق منها صفاخرى
في هذه الصف قمنا بملأ الواجهة
- الآن نقوم بعمل واجهة المتحكم في السقينة

```
// Adaptee interface
 public interface ISeacraft
 {
 int Speed { get; }
 void IncreaseRevs();
 }

```

كما نرى يحتاج فقط إلى الدالة IncreaseRevs وخاصية Speed
- الآن نقوم بوراثة الواجهة

```
// 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; }
 }
 }

```

قمنا بالوراثة من صف الـ Seacraft وواجهة الـ IAircraft وهذا بالطبع الزامي وذلك لعدم امكانيتنا في السي شارب ان نرث من أكثر من صف. الآن نحن قادرون من استخدام مميزات متعددة كمميزات السفينة والطائرة

الآن نقوم بوضع المفتاح ونقوم بتشغيل السفينة نورماندي

```
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:");
 ((ISeacraft)seabird).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!");
 }

```

```
/\* Output
 Experiment 1: test the aircraft engine
 Aircraft engine takeoff
 The aircraft engine is fine, flying at 200 meters
 Experiment 2: Use the engine in the Seabird
 Seacraft engine increases revs to 10 knots
 Seacraft engine increases revs to 20 knots
 Seacraft engine increases revs to 30 knots
 Seacraft engine increases revs to 40 knots
 Seacraft engine increases revs to 50 knots
 The Seabird took off
 Experiment 3: Increase the speed of the Seabird:
 Seacraft engine increases revs to 60 knots
 Seacraft engine increases revs to 70 knots
 Seabird flying at height 300 meters and speed 70 knots
 Experiments successful; the Seabird flies!

```

* أيقونة بوابةبوابة علم الحاسوب
* أيقونة بوابةبوابة تقانة المعلومات