Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Ćwieczenie z PHP OOP.
Forum PHP.pl > Forum > PHP > Object-oriented programming
siuda
Witam,

Od pewnego czasu ucze się programowania obiektowego i natrafiłem na takie zadanie :

"Utwórz klasę "rozwiazanie", która będzie mogła wykonać operacje arytmetyczne na takich tablicach jak array(5, "plus", 4), oraz array(2, "razy", 8) i wykonaj na nich działanie arytmetyczne. Pamiętaj, że środkowa wartość w tablicy jest również nazwą klasy - zaimplementuj ją. W przyszłości może być potrzeba obsługi innej operacji arytmetycznej bez potrzeby zmiany kodu".

Trochę nie rozumiem po co mam tworzyć jedną klasę "rozwiazanie", która i tak będzie musiała za pomocą funkcji array_search szukać takich słów jak plus, razy, minus, podzielić i wykonać operację na pozostałych wartościach. Jaki jest sens i potrzeba tworzenia kolejnych klas? Jeżeli ktoś może mi to wytłumaczyć to będe bardzo wdzięczny za pomoc. Nie jestem w stanie nawet zrobić sobie szkicu takiego rozwiązania jak to miałoby wyglądać.


Pozdrawiam,
Sephirus
Zadanie proste choć nietypowe... Mogę Ci napisać rozwiązanie ale wytłumaczyć dokładnie do czego to można zastosować to na chwilę obecną nie mogę wymyślić jakoś :/
Crozin
Trochę durny pomysł z przekazywaniem tych trzech informacji (dwie liczby, operacja) w formie tablicy, ale mniejsza z tym.

Ogólnie w ćwiczeniu chodzi o pokazanie pewnej dosyć popularnej struktury kodu zwanej strategią. W wiki masz podany całkiem przyzwoity opis tego wzorca projektowego.

Jaki jest sens tego wszystkiego? Przykładowo w tej chwili masz umożliwić realizację jedynie czterech operacji - dodawania, odejmowania, dzielenia oraz mnożenia. Mógłbyś to zrobić chociażby w takiej formie:
  1. public function wykonajOperacje($a, $b, $operacja) {
  2. switch ($operacja) {
  3. case 'dodawanie':
  4. return $a + $b;
  5. case 'odejmowanie':
  6. return $a - $b;
  7. case 'mnożenie':
  8. return $a * $b;
  9. case 'dzielenie':
  10. if ($b == 0) {
  11. throw new RuntimeException('Próba dzielenia przez zero');
  12. }
  13.  
  14. return $a / $b;
  15. default:
  16. throw new InvalidArgumentException('Nieznana operacja');
  17. }
  18. }
Jaki jest problem tego kodu? W przypadku chęci zmiany czegoś bądź dodania nowej operacji musimy zmodyfikować ten kod, a to wiąże się z pewnymi komplikacjami. Dodatkowo w przypadku gdyby każda z tych czterech operacji wymagała nieco więcej niż jednej linijki kodu powstałby straszny śmietnik, trudny do utrzymania, udokumentowania czy testowania.

Dlatego też same operacje wydzielamy do osobnych obiektów - wtedy wszystko mamy ładnie rozdzielone, dodanie nowej operacji jest proste i nieinwazyjne, a całością jest łatwiej zarządzać.

W polskiej wiki masz to ładnie opisane spróbuj to zaimplementować. Jeśli nie dasz rady skorzystaj z innych źródeł (angielska wiki, bądź Google i fraza php strategy pattern).

@Sephirus: Zadanie proste i bardzo, ale to bardzo typowe. wink.gif Może z tego opisu nie zrozumiałeś o co do końca chodzi.
siuda
@Sephirus:

Gdyby nie sprawiło ci to problemu to byłbym bardzo wdzięczny. Zadanie również wydaje mi się trochę zakręcone, ale chciałbym zobaczyć jak to działa w praktyce.
Sephirus
Najprościej jak można:

  1. class Rozwiazanie_plus
  2. {
  3. public function wykonaj($a,$b)
  4. {
  5. return $a+$b;
  6. }
  7. }
  8.  
  9. class Rozwiazanie_razy
  10. {
  11. public function wykonaj($a,$b)
  12. {
  13. return $a*$b;
  14. }
  15. }
  16.  
  17. class Rozwiazanie
  18. {
  19. public function wykonaj(array $tablica)
  20. {
  21. list($a,$klasa,$b) = $tablica;
  22. $klasa = 'Rozwiazanie_'.$klasa;
  23. // Tu przydałoby się jeszcze zaimplementować jakieś wczytywanie klasy
  24. // inlcude itd...
  25. $klasa = new $klasa();
  26. return $klasa->wykonaj($a,$b);
  27. }
  28. }
  29.  
  30. $r = new Rozwiazanie();
  31. echo $r->wykonaj(array(1,'plus',2)); // 3
  32. echo $r->wykonaj(array(3,'razy',7)); // 21


Oczywiście trzeba wrzucić jeszcze ładowanie klas (include) przy odpowiednim założeniu co do nazewnictwa. Osobiście dorzuciłbym do tego jeszcze interfejs:

  1. interface iRozwiazanie
  2. {
  3. public function wykonaj($a, $b);
  4. }


i wymusł jego używanie przy klasach typu Rozwiazanie_[operacja]:

  1. class Rozwiazanie_plus implements iRozwiazanie
  2. {
  3. public function wykonaj($a,$b)
  4. {
  5. return $a+$b;
  6. }
  7. }
  8.  
  9. class Rozwiazanie_razy implements iRozwiazanie
  10. {
  11. public function wykonaj($a,$b)
  12. {
  13. return $a*$b;
  14. }
  15. }


aby było jasne jaką metodę mają posiadać klasy do operacji arytmetycznych...

A co do tego że to nietypowe zadanie - nietypowe jest dla mnie przekazywanie tej tablicy smile.gif - dziwne tongue.gif

EDIT: acha i teraz jak chcesz dodać nową operację arytmetyczną na przykład potęgę to wystarczy dać napisac nową klase:

  1. class Rozwiazanie_potega
  2. {
  3. public function wykonaj($a,$b)
  4. {
  5. return pow($a,$b);
  6. }
  7. }
  8.  
  9. $r = new Rozwiazanie();
  10. echo $r->wykonaj(array(3,'potega',2)); // 9

siuda
Dziękuję bardzo za pomoc. To mi powinno trochę rozjasnić umysł. Największym problemem dla mnie jest chyba zmiana sposobu myślenia, wg wzorców projektowych, które jak widzę są koniecznością przy programowaniu obiektowym. Nie potrafię do końca sie "przełączyć" na OOP po wielu latach pisania proceduralnego, ale chyba nie jestem jedynym, który ma ten problem.
Orzeszekk
Najprosciej: Wyobraz sobie ze tych operacji arytmetycznych masz nie 4 a 300, i dodatkowo chcesz dac mozliwosc dodawania nowych operacji za pomocą plug-inów. Wtedy strategia staje sie baardzo sensowna.

Ogolnie strategia uczytelnia kod nawet dla kilku opcji, jesli sa one rozbudowane. Tworzysz klase abstrakcyjną - bazę ktora przechowuje wszystkie wspolne dla wszystkich strategii operacje, a do strategii finalnych dopisujesz tylko to czym sie roznia.

Jesli masz wszystkie mozlwiosci "zahardkodowane" switchami i ifami, pisząc jedną czesc algorytmu mozesz popsuc drugą (pomijajac fakt ze to cholernie nieczytelne). Gdy masz wyiozolowane roznice miedzy algorytmami w postaci strategii robiac jedną nie masz jak popsuc drugiej.

Dla prostych rzeczy wzorce projektowe wydaja sie nadmiarowe i niepotrzebne, swoja sile pokazuja przy duzych projektach.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.