제이온

[Obiekty] Rozdział 2. Programowanie obiektowe

  • Język oryginalny: Koreański
  • Kraj: Wszystkie krajecountry-flag
  • TO

Utworzono: 2024-04-28

Utworzono: 2024-04-28 13:46

System rezerwacji biletów na filmy


Przeglądanie wymagań

  • Chcemy zaimplementować system rezerwacji biletów na filmy online.
  • Film reprezentuje podstawowe informacje o filmie.
    • Tytuł, czas trwania, informacje o cenie itp.
  • Projekcja reprezentuje rzeczywiste wydarzenie, podczas którego widzowie oglądają film.
    • Data projekcji, godzina, numer kolejności itp.
  • Ludzie rezerwują bilety na filmy, ale właściwie powinniśmy powiedzieć, że rezerwują bilety na konkretną projekcjęfilmu.
  • Warunki zniżek
    • Możliwość obniżenia ceny.
    • Warunek kolejności: wykorzystanie numeru kolejności projekcji do ustalenia zniżki.
    • Warunek czasu: wykorzystanie godziny rozpoczęcia projekcji filmu do ustalenia zniżki.
  • Polityka zniżek
    • Ustalanie ceny po zniżce.
    • Polityka zniżki kwotowej: odliczenie określonej kwoty od ceny biletu.
    • Polityka zniżki procentowej: odliczenie określonego procentu od ceny standardowej.
  • Dla każdego filmu można przypisać jedną politykę zniżek lub w ogóle nie stosować zniżek, a warunki zniżek można łączyć.
  • Jeśli polityka zniżek jest zastosowana, ale warunki zniżek nie są spełnione lub polityka zniżek nie jest zastosowana, to cena biletu nie jest obniżana.


W kierunku programowania obiektowego

Współpraca, obiekty, klasy

  • Programowanie obiektowe to programowanie zorientowane na obiekty.
    • Nie należy zastanawiać się nad tym, jakie atrybuty i metody są potrzebne w klasie po jej zdefiniowaniu.
    • Należy ustalić, jakie obiekty mają jakie stany i zachowania.
    • Obiekty należy postrzegać nie jako niezależne jednostki, ale jako członków współpracującej społeczności.


Struktura programu zgodna ze strukturą domeny

  • Domena to dziedzina, w której użytkownik korzysta z programu w celu rozwiązania problemu.

<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fe7d22a03-4a24-40e9-8068-bd03b9fd816b%2FUntitled.png?table=block&id=3f1931fc-8ef9-470a-8189-3727146638f6&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/438;" width="2000" height="438"></span>

  • Zazwyczaj nazwa klasy powinna być taka sama jak odpowiadająca jej koncepcja domeny lub przynajmniej podobna.
  • Relacje między klasami powinny być jak najbardziej podobne do relacji między koncepcjami domeny, aby struktura programu była łatwa do zrozumienia i przewidywania.


Implementacja klasy

  • Klasa jest podzielona na część wewnętrzną i zewnętrzną. Aby zaprojektować dobrą klasę, należy zdecydować, które części udostępnić na zewnątrz, a które ukryć.
    • Atrybuty obiektu są blokowane jako prywatne, a metody potrzebne do zmiany stanu wewnętrznego są otwierane jako publiczne.
  • Rozróżnienie między częścią wewnętrzną i zewnętrzną klasy zapewnia autonomię obiektu, co z kolei daje programistom swobodę implementacji.


Autonomiczne obiekty

  • Obiekt powinien być autonomicznym obiektem posiadającym stan i zachowania.
  • Łączenie danych i funkcji w obrębie obiektu nazywa się inkapsulacją.
  • Kontrolowanie dostępu ogranicza ingerencję z zewnątrz, co pozwala obiektowi samodzielnie podejmować decyzje dotyczące własnych działań.
  • Zasada separacji interfejsu od implementacji jest jedną z głównych zasad, których należy przestrzegać w programowaniu obiektowym.
    • Interfejs publiczny: część dostępna z zewnątrz.
    • Implementacja: część dostępna tylko wewnątrz.


Swoboda programisty

  • Rola programisty jest podzielona na autora klasy i programistę klienta.
    • Autor klasy dodaje nowy typ danych.
    • Programista klienta używa typu danych dodanego przez autora klasy.
  • Ukrywanie implementacji
    • Autor klasy może ukryć wewnętrzną implementację przed programistą klienta, udostępniając tylko niezbędne części.
    • Programista klienta musi znać tylko interfejs, co zmniejsza ilość informacji, którą musi znać.


Współpracująca społeczność obiektów

  • Zamiast deklarować prostą zmienną typu Long do reprezentowania pieniędzy, lepiej jest zapakować ją w obiekt, np. Money. Użycie obiektu zapewnia lepszą komunikację znaczenia i pozwala na wykonywanie powtarzalnych operacji w jednym miejscu.
  • Współpracę między obiektami w celu realizacji konkretnej funkcji systemu nazywamy współpracą.


Krótka historia współpracy

  • Jedynym sposobem, w jaki obiekt może wchodzić w interakcję z innymi obiektami, jest wysyłanie lub odbieranie wiadomości.
  • Własną metodę obsługi otrzymanej wiadomości nazywamy metodą.
  • Rozróżnianie między wiadomością a metodą jest ważne, a stąd bierze się koncepcja polimorfizmu.


Obliczanie ceny po zniżce

Rozpoczęcie współpracy w celu obliczenia ceny po zniżce

  • Klasa Movie nie zawiera szczegółowej logiki dotyczącej polityki zniżek i deleguje ją do interfejsu DiscountPolicy. Wykorzystanie dziedziczenia, polimorfizmu i abstrakcji jest niezwykle ważne.


Polityka zniżek i warunki zniżek

<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F7b9b27a5-0dac-4ba7-9552-05b7f8fbdecd%2FUntitled.png?table=block&id=3264f189-6e12-4a55-94d2-75b851320c7a&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/535;" width="2000" height="535"></span>


Dziedziczenie i polimorfizm

Zależność w czasie kompilacji i zależność w czasie wykonywania

  • Zależność kodu i zależność w czasie wykonywania mogą się różnić.
  • Im większa różnica między tymi dwoma rodzajami zależności, tym trudniej zrozumieć kod, ale tym bardziej elastyczny i rozszerzalny staje się kod.


Programowanie oparte na różnicach

  • Dziedziczenie pozwala na łatwe i szybkie dodawanie nowych klas w oparciu o istniejące klasy, a także na ponowne wykorzystanie implementacji klasy nadrzędnej.
  • Tworzenie nowej klasy poprzez dodanie tylko różnic w stosunku do klasy nadrzędnej nazywamy programowaniem opartym na różnicach.


Dziedziczenie i interfejsy

  • Dziedziczenie powoduje, że klasa potomna dziedziczy wszystkie interfejsy udostępnione przez klasę nadrzędną.
  • Interfejs definiuje listę wiadomości, które obiekt może zrozumieć.
  • Movie wysyła do DiscountPolicy wiadomość calculateDiscountAmount. Dla Movie nie ma znaczenia, jaka klasa instancji odpowie, ważne jest tylko, aby odpowiedź była poprawna.
  • Dlatego zarówno AmountDiscountPolicy, jak i PercentDiscountPolicy mogą współpracować z Movie w imieniu DiscountPolicy.
  • Takie zastępowanie klasy potomnej przez klasę nadrzędną nazywamy konwersją w górę (upcasting). Wynika to z faktu, że klasa potomna jest automatycznie konwertowana na typ klasy nadrzędnej, co sprawia wrażenie, że znajduje się ona wyżej.


Polimorfizm

  • Polimorfizm to zdolność obiektu do reagowania na tę samą wiadomość w różny sposób w zależności od jego typu.
    • Movie wysyła tę samą wiadomość, ale metoda, która zostanie faktycznie wykonana, zależy od tego, jaka klasa obiektu odbierającego wiadomość.
  • Polimorfizm opiera się na fakcie, że zależność w czasie kompilacji i zależność w czasie wykonywania mogą się różnić.
  • Polimorfizm decyduje o metodzie do wykonania w czasie wykonywania, dlatego nazywamy go późnym wiązanie lub dynamicznym wiązaniem.


Interfejsy i polimorfizm

  • Jeśli nie chcemy udostępniać implementacji, a chcemy udostępniać tylko interfejs, to zamiast klasy abstrakcyjnej powinniśmy użyć interfejsu.


Abstrakcja i elastyczność

Siła abstrakcji

  • Zalety abstrakcji
    • Jeśli spojrzymy tylko na hierarchię abstrakcji, możemy opisać politykę wymagań na wysokim poziomie.
    • Projektowanie staje się bardziej elastyczne.


Elastyczne projektowanie

  • Abstrakcja zapobiega powiązywaniu projektu z konkretną sytuacją, co pozwala na stworzenie elastycznego projektu.


Kompromis między klasą abstrakcyjną a interfejsem


  • Obecnie klasa NoneDiscountPolicy jest w rzeczywistości zbędna, ponieważ metoda calculateDiscountAmount() klasy DiscountPolicy zwraca 0, jeśli nie ma żadnych warunków zniżek, więc nie ma problemu. Jednak z punktu widzenia użytkownika należy przekazać do Movie pustą politykę zniżek typu None, dlatego została ona dodana.
  • Dlatego klasa NoneDiscountPolicy jest myląca, a po modyfikacji będzie łatwiejsza do zrozumienia.



  • W ten sposób DiscountPolicy jest abstrakcyjnym interfejsem, a jego implementacjami są NoneDiscountPolicy (reprezentujący brak polityki zniżek) i DefaultDiscountPolicy (reprezentujący standardową politykę zniżek).

<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F712983a9-3937-4265-82fe-66a144c44a0f%2FUntitled.png?table=block&id=f5ca651c-d03c-4a6c-97e9-7443ee5649a0&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/886;" width="2000" height="886"></span>

  • Można uznać, że dodawanie interfejsu wyłącznie dla NoneDiscountPolicy jest nieefektywne w porównaniu do wzrostu złożoności.
  • Należy pamiętać, że wszystko, co implementujemy, jest przedmiotem kompromisu. Oznacza to, że każdy napisany przez nas kod musi mieć uzasadnienie.


Ponowne użycie kodu

  • Dziedziczenie może być używane do ponownego użycia kodu.
  • Jednak do ponownego użycia kodu lepiej jest używać kompozycji niż dziedziczenia.
  • W obecnym kodzie sposób, w jaki Movie ponownie używa kodu DiscountPolicy, to właśnie kompozycja.
  • Jeśli Movie byłoby klasą nadrzędną, a AmountDiscountMovie i PercentDiscountMovie klasami pochodnymi, to byłoby to dziedziczenie.


Dziedziczenie

  • Wady dziedziczenia
    • Narusza inkapsulację.
      • Należy dobrze znać wewnętrzną strukturę klasy nadrzędnej.
      • Zmiana klasy nadrzędnej prawdopodobnie spowoduje konieczność zmiany klasy potomnej.
    • Utrudnia elastyczność projektu.
      • Relacja między klasą nadrzędną a potomną jest ustalana w czasie kompilacji.
      • Nie można zmienić typu obiektu w czasie wykonywania.
      • Jednak w przypadku kompozycji można zmienić instancję w czasie wykonywania za pomocą metody takiej jak changeDiscountPolicy().


Kompozycja

  • Sposób ponownego użycia kodu wyłącznie za pomocą wiadomości zdefiniowanych w interfejsie nazywamy kompozycją.
  • Pozwala na implementację inkapsulacji i utrzymanie luźnego sprzężenia.
  • W przypadku polimorfizmu i ponownego użycia interfejsu należy łączyć dziedziczenie i kompozycję.
    • Na przykład interfejs DiscountPolicy musi używać dziedziczenia do implementacji jego podklas.


Źródło

  • Obiekty

Komentarze0

[Dla osób bez informatycznego wykształcenia, jak przetrwać jako programista] 14. Podsumowanie często zadawanych pytań na rozmowach kwalifikacyjnych dla początkujących programistówPodsumowując, przedstawiamy często zadawane pytania techniczne na rozmowach kwalifikacyjnych dla programistów (obszar pamięci, struktury danych, bazy danych itd.). Mamy nadzieję, że pomoże to w przygotowaniach do rozmowy kwalifikacyjnej.
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

April 3, 2024