Створення ядра програми управління освітленням в Visual C # (Sharp)

Система управління освітленням реалізується в два етапи На першому етапі пишеться вихідний код, який працює належним чином А на другому етапі у вирішення інтегрується код, написаний іншими програмістами Тут же виконується перевірка, що якщо даний код з якихось причин не працює належним оазом, то це не позначиться на коді, розробленому нами

Розробка даного додатка ускладнюється тією обставиною, що нам прихо працювати з невідомими У попередніх прикладах ми контролювали каий клас, інтерфейс і визначення На цей же раз у нас такої можливості повного контролю немає, і тому нам необхідно застосувати захисний стиль програмування Це означає, що нам потрібно розробити множинні теи і тримати певну інформацію приватною

Основним завданням контролера освітлення є управління освітленням в лой кімнаті будівлі Кімнати можна визначити і організувати за допомогою іерфейсов Інтерфейсів нам буде потрібно чотири А саме:

• iRoom – інтерфейс-заповнювач для концепції кімнати

• iNoRemotecontroiRoom-інтерфейс для кімнат, які не повинні упраяться контролером

• iRemotecontrolRoom-інтерфейс для кімнат, які повинні повністю управлятися контролером

• isensorRoom-інтерфейс для кімнат, в яких освітлення управляється стоянням (тобто присутністю чи відсутністю в них людей)

Інтерфейси для кімнат з керованим освітленням – IRemotecontrolRoom і isensorRoom-залежатимуть від певних логічних механізмів Ці інтерфейси повинні надавати вхідні дані і приймати вихідні даие Логічний механізм також може отримати інші дані, наприклад час дня чи рівень зовнішньої освітленості Все це зводиться до визначення якоїсь логіки, яка реалізується в ядрі Це є ключовим аспектом і подібно до відносин між батьками і дітьми У той час як батьки сприймають дітей як розумних істот, здатних приймати самостійні рішення, в кінцевому рахунку, остаточне рішення приймається батьками Таким же оазом, хоча ядро ​​може приймати до розгляду введення і пропоновані рішення, кінцеве рішення воно приймає самостійно

Інтерфейс IRoom

Для цілей розробки, найпростішою і базовою концепцією є кімната, корую можна визначити наступним чином (у бібліотеці контролера LibLightingSystem):

public interface IRoom { }

Цей інтерфейс не має жодних методів або властивостей, і називаєтьсязаполнітем Заповнює тип не має ніякого іншого призначення, крім як для УКАН, що реалізація відноситься до певного типу Застосування інтерфейсоаполнітелей спрощує групування обєктів з конкретними можливостями

Уявіть визначення обєктів без допомоги інтерфейсу-заповнювача Напрер, наступним чином:

class Typel {} class Туре2 {}

З цих визначень класів Typel і туре2 ми не бачимо ніякого взаємозвязку МДУ ними Не мається нічого, що дозволило б нам зробити висновок, що Typel і туре2 мають які-небудь загальні атрибути (Гаразд, технічно класи взаємоповязані в тому, що обидва є похідними класу object Але такий взаємозвязок те саме

тієї, що кожен з людей є людиною) Використовуючи інтерфейс-заповнювач, класи Typei і туре2 можна асоціювати один з одним таким чином:

class Typel : IRoom { } class Type2 : IRoom { }

IRoom[] rooms = new IRoom[10] rooms[0] = new Typel() rooms[1] = new Type2()

Реалізуючи інтерфейс IRoom класами Typel і туре2 і при цьому не роблячи нічого, окрім створення похідних класів від IRoom, ми створюємо взаємозвязок між класами Typel і туре2 Дана взаємозвязок полягає в тому, що як клас Typei, так і клас туре2 є кімнатами На даному етапі ми не знаємо, які кімнати вони представляють, чи знаходяться ці кімнати в одній будівлі і т п Все, що ми знаємо про них, – це лише те, що вони кімнати

При розробці ядра використання інтерфейсів-заповнювачів відіграє дуже ваую роль Заповнювач вказує, що тип повинен належати групі З помью групування ядро ​​може визначити список східних елементів Це щось подібне на запрашіваніе інформації про вік у претендента на отримання водельскіх прав Інформація про вік не містить ніякої іншої інформації про людину, наприклад підлогу, розумові здібності або відомості про його способнтях до водіння машини Це всього лише заповнювач, який вказує, явлтся дана людина членом групи, яка може отримати водійське посвідчення

У випадку з нашою системою управління освітленням, визначенням інтерфейсаполнітеля IRoom ми вказуємо, що будь-який екземпляр, асоційований з IRoom, повідомляє нам про своє бажання бути частиною ядра контролера управління освітлена Коли ми визначаємо тип за допомогою інтерфейсу-заповнювача, то указивм, що даний тип можна використовувати в конкретному контексті, який опредяется даними інтерфейсом-заповнювачем

ІнтерфейсINoRemoteControlRoom

Хоча по ідеї система повинна керувати освітленням у всьому будинку, деякі коати повинні бути виключені з системи Це можуть бути приватні кімнати або приміщення, в яких освітленням з якихось причин небажано упраять за допомогою контролера

Візьмемо, наприклад спальню Чи хочемо ми, щоб освітлення в ній управлялося контролером Якщо освітлення в спальні управляється автоматичним контролле, то існує можливість, що він може вимкнути світло, коли людина чує Або навпаки, контролер може включити світло, коли людина вирішила трохи подрімати Звичайно ж, в обох випадках людина може вручну виправити помилку контролера, але це будуть зайві клопоти, позбутися яких і було початковою метою встановлення контролера Так як незручність, причиняемое

помилками контролера, перевищує користь, принесену його правильними Дейсі, то контролер не повинен керувати освітленням в даній кімнаті

Визначення інтерфейсу (у бібліотеці контролера LibLightingSystem), вказавши, що висвітлення в даній комнатене управляється контролером, буде влядеть таким чином:

public interface INoRemoteControlRoom : IRoom { }

Так само як і інтерфейс-заповнювач IRoom, інтерфейс INoRemoteControlRoom не має ні методів, ні властивостей Але в даному випадку методи і властивості отсутствт, т к для ядра вони не потрібні Інтерфейс INoRemoteControlRoom служить для вказівки, що реалізує інтерфейс тип є кімнатою, але кімнатою, освітлення в якій не має управлятися контролером Використовуючи спальню як приклад, реалізація (певна у проекті ноті) виглядатиме таким чином:

class Bedroom : INoRemoteControlRoom {

}

Дане визначення кімнати дозволяє ядру використовувати примірник кімнати слующім чином:

IRoom[] rooms = new IRoom[10] rooms[0] = new Bedroom()

if (rooms[0] is INoRemoteControlRoom) {

/ / He робимо нічого і, можливо, змінюємо напрямок виконання коду

}

Даний код створює масив кімнат і привласнює елементу 0 масиву екземпляр класу Bedroom У операторі if виконується перевірка, чи не містить елемент 0 масиву екземпляр типу INoRemoteControlRoom

ПРИМІТКА

Використання інтерфейсів-наповнювачів і спадкування формує дуже моую архітектуру, що дозволяє створювати угруповання Згодом окремі еемпляри можна відфільтрувати на основі додаткових ознак в групі Все це можливо завдяки ключовими словами as і is, які дозволяють опитувати похідні типи екземпляра Дане опитування виконується неинвазивно і не викликає винятків Опитування дозволяє приймати рішення в залежності від того, чи потрібно асоціювати інтерфейс з певною угрупованням на основі інтерфейсу

ІнтерфейсIRemoteControlRoom

Ще одним типом кімнати є кімната, в якій освітлення повністю управляється контролером Для таких кімнат контролер не розраховує на введення з датчиків, а управляє освітленням на основі логіки, відповідний для определеятся кімнати

Наприклад, для виставкового залу музею для певних періодів дня освітлені не потрібно А після закінчення робочого дня і прибирання освітлення може бути вимкнено взагалі На початку ж робочого дня освітлення включається автоматічкі в певний час Така проста логіка може бути повністю реалізовувати контролером

Інтерфейс для кімнат з освітленням, повністю керованим контролером, оеделяется таким чином (у бібліотеці LibLightController):

public interface IRemotecontrolRoom : IRoom { double LightLevel { get }

void LightSwitch(bool lightState) void DimLight(double level)

}

Єдиним введенням, наданим інтерфейсом IRemotecontrolRoom, явлтся інформація про стан включеності освітлення і його рівня Дана іормація надається за допомогою властивості LightLevel Ця властивість доупно тільки для читання (у нього є лише оператор get), т к в іншому випадку може статися десинхронізація контролера і рівня освітлення

Наприклад, припустимо, що одного разу прибиральники затрималися у виставковому залі пле вимикання світла Щоб завершити збирання, вони включають освітлення вруую Місцевий пристрій може зробити одне з двох: дозволити ручне керуючи освітленням, не вимагаючи схвалення контролера, або ж заборонити це, вимагаючи втручання контролера Кращим підходом буде дозволити локальне ручне управління і дати прибиральникам включити світло Властивість LightLevel необхідно для того, що контролер міг упевнитися в тому, що стан освітлення тое, яким він його очікує

ПРИМІТКА

При визначенні ядра іноді потрібно додати в інтерфейс функціональність, яка перевіряє стан реалізації Так як ядро ​​не контролює реалізацію, то воно не повинн про робити припущень про стан, т к воно може змінитися з якоїсь причини У випадку з системою управління освітлення м така зміна може бути викликано включенням світла прибиральників м після того, як він би л вимкнений

Методи LightSwitch () і DimLight () класу IRemotecontrolRoom включають І влючає освітлення і встановлюють його рівень, відповідно За допомогою цих методів здійснюється контроль стану реалізації

Інтерфейс ISensorRoom

Нарешті, є ще один тип кімнати – освітлення в якій управляється короллером за певних обставин Повернемося до нашого прикладу з затрималися прибиральниками, включившими вручну освітлення, вимкнене контролером Якщо контролер виявить, що висвітлення включено після того, як він вимкнув його, чи повинен він вимкнути його знову Однією з відповідей може

бути, що контролер повинен вимкнути освітлення знову Але це буде непрільний відповідь Уявіть собі ситуацію, коли прибиральник включає освітлення, а контролер відразу ж вимикає його Природно, прибиральник включає освітлення знову, але і контролер теж знає свої обовязки і відразу ж вимикає його Бучі мислячою людиною, прибиральник придумує спосіб перемогти контролер – закріпити вимикач під включеному положенні, скажімо, скотч-стрічкою Це вивала безперервне включення і виключення освітлення, але оскільки інтервал між протилежними станами вимірюється в мілісекундах, то практічкі освітлення залишається включеним Хоч такий підхід і дасть бажаний практескій результат, краще було б поставити на вимикач таймер, що дозволяє висвітленню залишатися включеним на певний період часу після руого включення Але і тут є своя проблема Скільки часу має освітлено залишатися включеним

Ще одним способом буде не використання таймера, а поліпшення інтерфейсу, щоб дозволити контролеру дізнатися стан освітлення Такий поліпшений інтерфейс, який називається isensorRoom, визначається в бібліотеці класу LibLightcontroller: public interface ISensorRoom: IRemoteControlRoom {

bool IsPersonlnRoom { get }

}

Інтерфейс isensorRoom має одне булево властивість IsPersonlnRoom Значення true даної властивості означає, що в кімнаті присутні люди в прото випадку – значення false – кімната вільна від людей Яким чином реалізація визначає наявність або відсутність людей у ​​кімнаті, що ні явлтся проблемою ядра, т к воно передбачає, що реалізація знає, яким чином дізнатися про це

ПРИМІТКА

Як правило, ядро ​​може взаємодіяти з реалізацією тільки через інтерфейс Ядро ніколи не повинно припускати певну реалізацію інтерфейсу Воно повинно застосовувати підхід, при якому воно отримує те, що бачить Таким чином, якщо ядру потрібна додаткова інформація, необхідно спроектувати раіреніе інтерфейсу або реалізувати новий інтерфейс Звичайно ж, це не означт, що необхідно розширювати інтерфейс для кожного можливого стану Іноді необхідно визначити конкретний інтерфейс (iCanadianTaxEngine), як в примі з податковим додатком у попередньому розділі

Тепер, коли у нас є всі готові інтерфейси, можна приступити до реалаціі ядра

Джерело: Гросс К С # 2008: Пер з англ – СПб: БХВ-Петербург, 2009 – 576 е: ил – (Самовчитель)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*