Ponieważ nie umiem wymyślić ciekawego wstępu do artykułu o wzorcu projektowym dlatego nie tak od razu przejdę do rzeczy. Doszło do mnie kilka opinii (zwłaszcza wczoraj przy wódzie - ja tam dużo nie piję bo to nie jest zdrowe ale inni tak), że poprzedni wpis był za długi i było w nim za mało cycków. Po pierwsze to ludzie wstydźcie się bo takie uwagi są w ogóle bardzo bardzo niedobre, bardzo bardzo złe. Po drugie chociaż bardzo bym chciał to jednak wydaje mi się, że nie mogę sobie wklejać losowych cycków (nawet tych sztucznych) z internetu bo to łamie jakieś tam prawa autorskie. Pozostaje mi tylko nauczyć się rysować cycki w paincie co może nie być złym pomysłem zważywszy na to, że zawsze kiedy koloruję ramki tabelek w css odczuwam niesamowity relaks i spadek ciśnienia krwi.
Wzorzec command bardziej funkcyjnie
Na Wikipedii wzorzec jest opisany i jest nawet przykład w scali - ale ów przykład wydaje mi się trochę lewy :http://en.wikipedia.org/wiki/Command_pattern
Jakby to można było napisać inaczej ?
type Command = () => Unit type KanalInformacji= String=>UnitNa początku dla porządku zadeklarujmy dwa typy. Ponieważ komenda standardowo ma metodę execute, która nic nie zwraca, więc i tutaj mamy "funkcję" bezzwrotną i bezparametrową. A KanalInformacji to taki typ dla bajeru, że niby wysyłamy coś kanałem informacji. Dodatkowo ostatnio przeczytałem, że posługując się innymi językami ludzie używają trochę innych rejonów w mózgu, więc taki ponglish może być ciekawym sposobem aby zyskać nową perspektywę
class Egzekutor { var historia: Vector[Command] = Vector() def execute(command:Command)={ historia=historia :+ command command() } def replay()={ historia.foreach(_.apply) } }W odróżnieniu od filmu z Arnoldem powyższy egzekutor po prostu wykonuje komendy i zapisuje je w historii coby replaya strzelić jak trza.
def commandFunction(kanalInformacji:KanalInformacji)(wiadomosc:String)()={ kanalInformacji(wiadomosc) } def wyslijNaEkran(wiadomosc:String)=println(wiadomosc) val ekranCommand=commandFunction(wyslijNaEkran)_ val ekranONCommand=ekranCommand("ON") val ekranOFFCommand=ekranCommand("OFF")To jest bardzo ale to bardzo ciekawy fragment. PNie wiem jak w tej kolorowance kodu pogrubić konkretne fragmenty także powiem na co trzeba zwrócić uwagę
- Trzecia para nawiasów w pierwszej linii. To jest potrzebne aby po wywołaniach w liniach 6 i 7 nie otrzymać wartości a funkcję bezparametrową : ekranONCommand : () => Unit = <function0>. Jeśli można inaczej to ja nie znam.
- W linii piątej jest na końcu taki podkreślnik, który oznacza, że aplikujemy tylko pierwszy argument do funkcji i w wyniku mamy : ekranCommand : String => (() => Unit) = <function1>
- I generalnie jest zajebista kompozycja. Można sobie tworzyć wiele kanałów komunikacji i wysyłać wiadomości
egzekutor.execute(ekranONCommand) //> ON egzekutor.execute(ekranONCommand) //> ON egzekutor.execute(ekranOFFCommand) //> OFF egzekutor.execute(ekranOFFCommand) //> OFF egzekutor.execute(ekranONCommand) //> ON egzekutor.replay //> ON //| ON //| OFF //| OFF //| ONI elegancko:
Posłowie (W sensie literackim a nie ci złodzieje!)
No i widzimy, że można sobie ładnie zaimplementować wzorzec Command przy pomocy funkcji. Nie wiem czy to tutaj przedstawiłem w 100% pokrywa się z klasycznym wzorcem ale tak w głębi serca mnie to jebie. Pozostaje jeszcze jedna kwestia - co jeśli nie znasz scali i nie możesz rozszyfrować co w tym kodzie jest popisane? Nie przejmuje się - kim jesteś? JESTEŚ ZWYCIĘZCĄ!!!!
* * *
Brak komentarzy:
Prześlij komentarz