Sr-12-wyk-1.0-Slajd11
Adapter – przykład realizacji
Ponieważ adapter nie posiada statycznej wiedzy o interfejsach obiektów, które obsługuje, jego konstrukcja musi być generyczna, niezależna od interfejsów obiektów. Na rysunku ukazano koncepcję współpracy adaptera ze szkieletami obiektów w postaci fragmentu kodu.
Jest to przykład adaptera, który zarządza wieloma obiektami. Adapter oczekuje, że szkielety obiektów implementują operację invoke(unsigned in_size, char in_args[], unsigned* out_size, char* out_args[]), w której parametr in_args jest tablicą bajtów, kryjącą w sobie identyfikację wywoływanej metody oraz wartości wszystkich jej argumentów. Odtworzeniem tych informacji z tablicy in_args zajmuje się szkielet, gdyż to właśnie on zna format tej tablicy, i zarazem jest odpowiedzialny za wywołanie metody. Parametr in_size określa rozmiar tablicy in_args . W podobny sposób, wynik jest przetwarzany przez szkielet do postaci tablicy bajtów out_args , a jej rozmiar zawiera parametr out_size .
Ukazany na rysunku fragment pliku nagłówkowego adaptera ukazuje w pierwszej kolejności ogólną strukturę wiadomości, które adapter wymienia ze zdalnymi klientami. Od każdego klienta oczekuje się, że swoje wywołania przetworzy do postaci obejmującej pięć pól. Wyniki wywołań są przetwarzane przez adapter do tej samej postaci, obejmującej pięć pól. Znaczenie pól jest następujące:
- source oznacza nadawcę wiadomości
- object_id i method_id identyfikują obiekt oraz wywoływaną w nim metodę
- tablica data wskazuje na wartości parametrów metody
- size informuje o rozmiarze tych parametrów.
Po zrealizowaniu wywołania ewentualne wyniki są umieszczane w polu data nowej wiadomości.
W dalszej części pliku znajduje się kluczowa definicja typu METHOD_CALL, czyli typu operacji, której realizacji adapter oczekuje od szkieletów, i której wywołanie przez adapter będzie oznaczało przekazanie wywołania szkieletowi. Zastosowanie wskaźnika na funkcję jako typu pozwala tutaj osiągnąć wspomnianą generyczność adaptera.
Spośród ostatnich trzech operacji dwie pierwsze wywołuje w adapterze serwer, po to by zarejestrować lub odrejestrować obiekt. Zauważmy, że podczas rejestracji szkielet przekazuje adapterowi wskazanie call na właściwą implementację operacji obiektu, a w wyniku otrzymuje od adaptera identyfikator obiektu. Później, podczas odrejestrowania obiektu, szkielet przekazuje jako parametr tylko identyfikator usuwanego obiektu.
Faktyczne wywołanie realizuje ostatnia z ukazanych operacji, invoke_adapter. Pośrednik ORB wywołuje ją zawsze po odebraniu z sieci komunikatu zawierającego wywołanie klienta.