→ Пошук по сайту       Увійти / Зареєструватися
Знання Патерни Структурні патерни — Structural patterns

6. Адаптер — Adapter

6.	Адаптер — Adapter

З деяких причин я дуже довго думав над тим, який же може бути хороший приклад для Адаптера. Можна навести приклад, коли є операції, які так і називаються: ОпераціяА та ОпА, або придумати складний приклад з великою кількістю методів і пропертів в класі, що адаптується... Але весь цей час в думках у мене крутилася така штукенція, яку ми соваємо у розетку, коли вона вузька, ще СРСР-рівська, а ми хочемо запхати шнур для живлення ноутбука із товстою вилкою. Майже, як на ілюстрації, але не настільки жорстока.

Отож, у нас є вилка від зарядного пристрою, яка підходить в широкі роз’єми. В одній із квартир у нас все сучасне, тому NewElectricitySystem має метод MatchWideSocket, яким ми просто можемо скористатися. В іншій квартирі у нас проблемки, тому OldElectricitySytem має тільки метод MatchThinSocket. Нажаль ми не можемо собі дозволити взяти дрель і роздовбати отвори в розетці. Натомість ми купуємо адаптер, який надає можливість користуватися тією ж функціональністю споживання електричного струму, але із старої системи.

Адаптер надає можливість користуватися об’єктом, який не є прийнятним у нашій системі і який не можна змінити. Ми адаптуємо його функціональність через інший, відомий нашій системі, інтерфейс.

Уривок коду 6.1. Читаємо код і вникаємо

 // Система яку будемо адаптовувати
class OldElectricitySystem
{
    public string MatchThinSocket()
    {
        return "220V";
    }
}
// Широковикористовуваний інтерфейс нової системи (специфікація до квартири)
interface INewElectricitySystem
{
    string MatchWideSocket();
}
// Ну і власне сама розетка у новій квартирі
class NewElectricitySystem : INewElectricitySystem
{
    public string MatchWideSocket()
    {
        return "220V";
    }
}

// Адаптер назовні виглядає як нові євроразетки, шляхом наслідування прийнятного у // системі інтерфейсу
class Adapter : INewElectricitySystem
{
    // Але всередині він таки знає, що коїлося в СРСР
    private readonly OldElectricitySystem _adaptee;
    public Adapter(OldElectricitySystem adaptee)
    {
        _adaptee = adaptee;
    }
    // А тут відбувається вся магія -
    // наш адаптер «перекладає»
    // функціональність із нового стандарту на старий
    public string MatchWideSocket()
    {
        // Якщо б була різниця в напрузі (не 220V)
	     // то тут ми б помістили трансформатор
        return _adaptee.MatchThinSocket();
    }
}

class ElectricityConsumer
{
    // Зарядний пристрій розуміє тільки нову систему
    public static void ChargeNotebook(INewElectricitySystem electricitySystem)
    {
        Console.WriteLine(electricitySystem.MatchWideSocket());
    }
}

public class AdapterDemo
{
    public static void Run()
    {
        // 1)
        // Ми можемо користуватися новою системою без проблем
        var newElectricitySystem = new NewElectricitySystem();
        ElectricityConsumer.ChargeNotebook(newElectricitySystem);

        // 2)
        // Ми повинні адаптуватися до старої системи, використовуючи адаптер
        var oldElectricitySystem = new OldElectricitySystem();
        var adapter = new Adapter(oldElectricitySystem);
        ElectricityConsumer.ChargeNotebook(adapter);
    }
}

Попрошу ще раз повернутися до коду і переконатися, що ви прочитали усі коментарі, а взаємодія між класами була зрозуміла. Для кращого засвоєння, візьміть ручку і на будь-якому «огризку» паперу намалюйте UML до цієї реалізації патерну Адаптер, а потім узагальніть.

Насправді в реалізації не є обов’язковою композиція adaptee. Також наш клас Adapter міг би одночасно реалізовувати два інтерфейси — нової і старої системи. А зробивши два конструктори (а чому б і ні?), ми б могли одного разу створити його на базі нової, а іншого — на базі старої системи. Це б дозволило використовувати його в обидва боки. Натиснувши собі якусь кнопку, ваш адаптер перетворюється «шиворіт-на-виворіт».

По матеріалам книги Андрія Будая "Дизайн патерни – просто, як двері". Матеріал розміщується за домовленістю з автором.
Робота представлена за умовами ліцензії Creative Commons Attribution-NonCommercial 3.0 Unported License.

загрузка...
Сторінки, близькі за змістом