Софтуерно Инженерство
Loading...
ArmenPotourlyan avatar ArmenPotourlyan 488 Точки

[Exercises][C# OOP Advanced] - Reflection - Problem{6} - Mirror Image

Здравейте, колеги,



Бих искал да споделя една интересна (поне за мен) идея за решение на задачата: Магьосникът държи две полета от тип магьосник в себе си - за двете копия, и съответно всеки път като прави заклинание за раздвояване, се създават инстанции за копията. Т.е. магьосникът може да се разгледа като двоично дърво - най-отгоре стои оригиналът, който се разклонява към други две копия, те от своя страна към максимум други две копия и т.н.

private Wizard leftWizardReflection;
private Wizard rightWizardReflection;

 

При такава структура за изпълнението на заклинанията е достатъчно да се обходи магьосника с рекурсивен Depth-First Search Pre-order алгоритъм. При този алгоритъм рекурсивно се обхожда първо едната част, после другата част на дървото (от някой стартов възел - в случая магьосник). Ето как изглеждат заклинанията:

public void CastReflectionSpell()
{
    this.ReflectionSpellCasted?.Invoke(this, EventArgs.Empty);
    this.CastReflectionSpell(ref this.leftWizardReflection);
    this.CastReflectionSpell(ref this.rightWizardReflection);
}

public void CastFireballSpell()
{
    this.FireballSpellCasted?.Invoke(this, EventArgs.Empty);   
    this.CastFireballSpell(ref this.leftWizardReflection);
    this.CastFireballSpell(ref this.rightWizardReflection);
}

ReflectionSpellCasted и FireballSpellCasted са еvent-и, към които можем да се закачим отвън :))) И съответно при всяко извикване от оригиналния магьосник или от някое от копията му - се вдигат event-ите последователно първо по лявото разклонение, после по дясното, така, както се иска в условието на задачата.

Как да избираме обаче точно определено копие на магьосника като начален възел? Тук определено ми куца структурата - аз съм решил проблема със статичен речник <int, Wizard>, който държи срещу id съответния Wizard. Направил съм индексатор, който да връща стойностите от речника:

public Wizard this[int index] => wizardById[index];

Какъв е недостатъка с този подход? Няма да мога да направя друг оригинален магьосник, понеже статичният речник е споделен за всички инстанции на Wizard... Разбира се, специално за тази задача няма значение - имаме нужда само от един оригинален магьосник. Все пак дали можете да предложите идея как да направя достъпа до даден възел (копие на маг), така че да мога да инстанцирам безопасно колкото си искам нови оригинални магьосници?

Ето как изглежда целия клас: Wizard

Тагове:
1
C# OOP Advanced 28/07/2016 11:58:06
StaVykoV avatar StaVykoV 169 Точки

DFS ми беше първата мисъл като видях тази задача. По принцип си мисля, че може да се реши без репозитори и евенти, но няма много смисъл.


Решение без репозитори:
Магията и айдито на кастъра се пускат винаги на първия магьосник, те после се предават надолу по дървото, докато не сен амери магьосника с айдито. Когато се открие, от него започва самото изпълнение на магията надолу.

Недостатъка е, че може да стане така, че да се обхождат доста магьосника докато се намери правилния, докато от репозиторито има достъп веднага. Плюс не виждам голям, освен малко спестена памет.

 

Решение с репозитори:

Просто частно репозитори което слуша за създаден нов магьосник. Така магьосниците няма да знаят за самото репозитори.

ID- то може да се генерира от нициализиран IDGenerator който си се предва по магьосниците от едно дърво. Той ще е реално просто еидн клас който прави ++ на int и го връща. Или просто може да се бутат в лист и от там автоматично да се генерира Id

Eто го моето решение - ЦЪК
Мисля си, че има по - добър вариант като например магиите да се изкарат във фактори, но в 5 сутринта малко ми е писнало и го оставям така :D

1
06/08/2016 05:24:16