Поєднання шаблонного методу із стратегією


14

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

  • Спосіб обробки результату переміщення
  • Спосіб визначення кінця гри
  • Спосіб визначення переможця

Перше, що мені прийшло в голову розробити це, - це використовувати шаблон стратегії, у мене є варіація алгоритмів (власне правила гри). Дизайн може виглядати приблизно так: введіть тут опис зображення

Тоді я подумав собі, що в грі Манкала та Варі спосіб визначення переможця точно такий же, і код буде дублюватися. Я не думаю, що це, за визначенням, порушення принципу «одне правило, одне місце» або DRY, оскільки сприйняття змін у правилах для Mancala не означає автоматично, що це правило слід змінювати і у Wari. Тим не менш, з відгуків, отриманих від мого професора, у мене склалося враження знайти інший дизайн.

Потім я придумав це: введіть тут опис зображення

Кожна гра (Mancala, Wari, Kalah, ...) просто матиме атрибут типу інтерфейсу кожного правила, тобто, WinnerDeterminerякщо є версія Mancala 2.0, яка є такою ж, як Mancala 1.0, за винятком того, як визначається переможець, він може просто використовувати версії Mancala.

Я вважаю, що реалізація цих правил як структури стратегії, безумовно, справедлива. Але справжня проблема виникає тоді, коли я хочу її розробити далі.

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

  • закладайте камені в отвори (це однаково для всіх ігор, тому це було б реалізовано в самому методі шаблону)
  • визначте результат переїзду
  • визначте, чи закінчилась гра через попередній хід
  • якщо гра закінчена, визначте, хто переміг

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

Я насправді не бачу різниці в дизайні між схемою стратегії та цією? Але я впевнений, що мені потрібно використовувати шаблонний метод (хоча я був так само впевнений, що потрібно використовувати шаблон стратегії).

Я також не можу визначити, хто буде нести відповідальність за створення TurnTemplateоб'єкта, тоді як за схемою стратегії я відчуваю, що у мене є сім'ї об'єктів (три правила), які я міг би легко створити, використовуючи абстрактний заводський зразок. Потім у мене з'явиться а MancalaRuleFactory, WariRuleFactoryі т. Д., І вони створюють правильні екземпляри правил і передають мені RuleSetоб'єкт.

Скажімо, я використовую стратегію + абстрактний заводський візерунок і в мене є RuleSetоб'єкт, який має алгоритми для трьох правил у ньому. Єдиний спосіб, коли я можу все-таки використовувати шаблон шаблону методу для цього, - це передавати цей RuleSetоб’єкт своєму TurnTemplate. «Проблема», що виникає тоді, полягає в тому, що мені ніколи не знадобляться мої конкретні реалізації TurnTemplateцих класів, вони б застаріли. У моїх захищених методах в TurnTemplateя міг просто зателефонувати ruleSet.determineWinner(). Як наслідок, TurnTemplateклас більше не буде абстрактним, а повинен стати конкретним, чи тоді це все ще шаблон шаблону методу?

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


1
Я б сказала, що ваше мислення є майже на місці. Якщо відгуки, які ви отримаєте від свого професора, не підтверджують це, попросіть його / її вказати на недоліки або підкажіть, що (він) має у відповіді. Перестаньте намагатися читати думки. Якщо припустити, що саме те, чого хоче ваш професор (а згодом і ваші користувачі), можливо, це найгірше, що ви можете зробити.
Мар'ян Венема

" ... в грі Манкала і Варі спосіб визначення переможця точно такий же, і код буде дублюватися. Чому це означає, що код дублюється? Просто нехай обидва класи називають одну і ту ж функцію.
D Drmmr

Відповіді:


6

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

У своєму першому дизайні ви оголошуєте, RuleInterfaceщо це інтерфейс, який визначає, як обробити поворот кожного гравця, як визначити, чи закінчена гра та як визначити переможця після закінчення гри. Здається, що це дійсний інтерфейс для сімейства ігор, які відчувають різні варіанти. Однак, залежно від ігор, у вас може бути дублюваний код. Я погоджуюся, що гнучкість змінювати правила однієї гри - це гарна річ, але я також стверджую, що дублювання коду страшно для дефектів. Якщо ви копіюєте / вставляєте несправний код між реалізаціями, а в одному є помилка, тепер у вас є кілька помилок, які потрібно виправити в різних місцях. Якщо ви переписуєте реалізації в різний час, ви можете вводити дефекти в різних місцях. Жодне з них не бажане.

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

Ваш третій дизайн - це той, який мені подобається найкраще. Мене єдине занепокоєння полягає в тому, що це не на правильному рівні абстракції. Зараз ви, здається, моделюєте поворот. Я б рекомендував розглянути можливість створення гри. Подумайте, що у вас є гравці, які роблять рухи на якійсь дошці, використовуючи камені. Ваша гра вимагає, щоб ці актори були присутніми. Звідти ваш алгоритм - не, doTurn()але playGame()переходить від початкового переходу до остаточного, після чого він припиняється. Після кожного ходу гравця він коригує стан гри, визначає, чи гра перебуває в остаточному стані, а якщо є, визначає переможця.

Я рекомендую детальніше ознайомитись із вашим першим та третім дизайном та працювати з ними. Це також може допомогти продумати прототипи. Як виглядатимуть клієнти, які використовують ці інтерфейси? Чи має один підхід до дизайну більше сенсу для впровадження клієнта, який насправді повинен створити гру і пограти в неї? Вам потрібно усвідомити, з чим це взаємодіє. У вашому конкретному випадку це Gameклас та будь-які інші пов'язані елементи - ви не можете конструювати ізольовано.


Оскільки ви згадуєте, що ви студент, я хотів би поділитися кількома речами з часу, коли я був спеціалістом технічної допомоги на курсі дизайну програмного забезпечення:

  • Візерунки - це просто спосіб зйомки речей, які працювали в минулому, але абстрагування їх до того моменту, коли вони можуть бути використані в інших проектах. Кожен каталог шаблонів дизайну дає назву шаблону, пояснює його наміри та місце його використання та ситуації, коли це в кінцевому рахунку стримує ваш дизайн.
  • Дизайн поставляється з досвідом. Найкращий спосіб заробити дизайн - це не просто зосередитись на аспектах моделювання, а усвідомити, що входить у реалізацію цієї моделі. Найелегантніший дизайн корисний, якщо його не вдається легко здійснити або він не вписується у більшу конструкцію системи або з іншими системами.
  • Дуже мало конструкцій є "правильними" чи "неправильними". Поки конструкція відповідає вимогам системи, вона не може помилитися. Після того, як буде відображено кожну вимогу з деяким уявленням про те, як система відповідає цій вимозі, дизайн не може помилитися. Наразі це лише якісне відношення до таких понять, як гнучкість чи повторність використання, доказовість чи ремонтопридатність.

Дякую за чудову пораду, особливо за вашу думку про те, що це було на неправильному рівні абстракції. Я змінив це зараз на таке, GameTemplateщо відчуває себе набагато краще. Це також дозволяє мені комбінувати заводський метод для ініціалізації гравців, дошки тощо
Mekswoll

3

Ваша плутанина виправдана. Вся справа в тому, що візерунки не є взаємовиключними.

Метод шаблонів - це основа для ряду інших шаблонів, таких як Стратегія та Держава. По суті, інтерфейс стратегії містить один або кілька методів шаблону, кожен з яких вимагає, щоб усі об'єкти, що реалізують стратегію, мали (принаймні) щось на зразок методу doAction (). Це дозволяє замінити стратегії одна на іншу.

У Java інтерфейс - це не що інше, як набір методів шаблонів. Так само, будь-який абстрактний метод є по суті шаблонним методом. Цей зразок (серед інших) був добре відомий дизайнерам мови, тому вони його вбудували.

@ThomasOwens пропонує чудові поради щодо підходу до вашої конкретної проблеми.


0

Якщо ви відволікаєтесь на дизайнерські зразки, моєю порадою вам буде спочатку прообразувати гру, тоді шаблони повинні просто вискочити на вас. Я не думаю, що це справді можливо або доцільно спершу спробувати спроектувати систему, а потім реалізувати її (подібним чином я вважаю, що це здивує, коли люди намагаються спочатку написати цілі програми, а потім компілювати, а не робити це поступово .) Біда полягає в тому, що навряд чи ви будете придумувати кожен сценарій, з яким доведеться мати справу з логікою, і на етапі впровадження ви або втратите надію, або спробуєте дотримуватися свого оригінального недосконалого дизайну та запровадите хакі, або навіть гірше взагалі нічого не доставляють.


2
Хоча загалом я з вами згоден , це насправді не відповідь, яка вирішує проблему ОП. "Не робіть цього" - це відповідь, але досить бідна, якщо вона не забезпечує життєздатну альтернативу.
янніс

@YannisRizos І хоча я також з вами згоден , я все ще думаю, що він дав слушні поради (або розуміння, якщо порада не є правильним словом). З цієї причини +1. Хоча так, це технічно не дуже корисна відповідь.
купив777

-1

Давайте перейдемо до латунних кронштейнів. Тут абсолютно немає необхідності в будь-якому ігровому інтерфейсі, немає моделей дизайну, немає абстрактних класів і UML.

Якщо у вас є достатня кількість класів підтримки, таких як інтерфейс користувача, моделювання та будь-яке інше, то в основному весь ваш неігровий логічний код все одно використовується повторно. Більше того, ваш користувач не змінює свою гру динамічно. Ви не перегортаєте на 30 Гц між іграми. Ви граєте в одну гру близько півгодини. Тож ваш "динамічний" поліморфізм насправді зовсім не динамічний. Це досить статично.

Тож розумний спосіб піти сюди - використовувати загальну функціональну абстракцію, як, наприклад, C # Actionабо C ++ std::function, створити один Манкала, один Варі та один клас Калах і піти звідти.

std::unordered_map<std::string, std::function<void()>> games = {
    { "Kalah", [] { return Kalah(); } },
    { "Mancala", [] { return Mancala(); } },
    { "Wari", [] { return Wari(); } }
};
void play() {
    std::function<void()> f;
    f = games[GetChoiceFromUI()];
    f();
    if (PlayAgain()) return play();
}
int main() {
    play();
}

Зроблено.

Ви не називаєте Ігор. Ігри закликають вас.


3
Я не бачу, як це взагалі корисно. Особа, яка задає це питання, - студент. Він чітко запитує про принципи дизайну та взаємодії між двома моделями дизайну. Сказати, що немає необхідності в моделях дизайну або UML може бути правдою в деяких випадках в промисловості, але роздуми про дизайнерські моделі, шаблони дизайну та UML можуть бути точкою вправи, про яку потрібно запитати.
Томас Оуенс

3
Про них нічого сказати, тому що ніде вони не застосовуються. Немає сенсу витрачати свій час на роздуми над тим, як би ви повністю підготували дизайн, використовуючи шаблони дизайну, якщо тільки ви не збираєтесь це бути уроком того, як їх не використовувати.
DeadMG

4
У SoftDev є тривожна / дратівлива тенденція, коли використовувані дизайнерські моделі вважаються важливішими, ніж просто вирішення проблеми. Існує таке поняття, як надмірна інженерія.
Джеймс

2
@DeadMG: хоча ви обоє по праву, у випадку ОП проблема полягає в здачі іспиту, а рішенням цієї проблеми є використання моделей дизайну та UML. Як би ми не мали рації, якщо його професор не погодиться з його рішеннями, він не пройде.
Горан Йович

2
Моя вся життя я завжди думав , що це був «латунь податок» ... Нічого собі, «мідні цвяхи» робить набагато більше сенсу. lol
купив777
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.