Programowanie komponentowe jesień-zima 2013

Slides:



Advertisements
Podobne prezentacje
Tablice 1. Deklaracja tablicy
Advertisements

Wstęp do strumieni danych
C++ wykład 2 ( ) Klasy i obiekty.
C++ wykład 4 ( ) Przeciążanie operatorów.
Język C/C++ Funkcje.
Programowanie obiektowe
Deklaracje i definicje klas w C++ Składowe, pola, metody Konstruktory
Programowanie obiektowe
Wzorce.
Prowadzący: mgr inż. Elżbieta Majka
PROGRAMOWANIE STRUKTURALNE
Wydajne aplikacje na platformie .NET
Nowa wersja C# Autor: Piotr Sobczak
Serwery Aplikacji ASP .NET Web Objects Arkadiusz Popa.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 6: Tablice, rekordy, zbiory.
Struktury.
Tablice.
C++ wykład 2 ( ) Klasy i obiekty.
Zasady zaliczenia Warunki uzyskania zaliczenia:
Typy prywatne 1 Typy prywatne W Adzie typy prywatne (private types) służą do bezpiecznego udostępniania danych zdefiniowanych w pakiecie, z którego korzysta.
Wykład 1: Wskaźniki Podstawy programowania Programowanie w C
Podstawy programowania PP – LAB5 Wojciech Pieprzyca.
Wykład 2 struktura programu elementy języka typy zmienne
Enteprise Java Beans Emil Wcisło.
1 Języki i techniki programowania prowadzący dr Grzegorz Filipczyk.
Tablice tablica jest sekwencją elementów tego samego typu (prostego lub obiektowego) w Javie tablice są obiektami, a zmienne tablicowe przechowują referencję
Wstęp do kontenerów IoC
Podstawy C# Grupa .NET PO.
Podstawy programowania
Podstawy programowania II
Programowanie urządzeń mobilnych – wykład IV
Podstawy informatyki 2013/2014
TABLICE C++.
Podstawy programowania
Programowanie obiektowe III rok EiT
Andrzej Repak Nr albumu
Java – coś na temat Klas Piotr Rosik
Inicjalizacja i sprzątanie
Programowanie obiektowe Wykład 3 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21 Dariusz Wardowski.
Podstawy informatyki 2013/2014
Przekazywanie parametrów do funkcji oraz zmienne globalne i lokalne
Programowanie obiektowe 2013/2014
ZWIĄZKI MIĘDZY KLASAMI KLASY ABSTRAKCYJNE OGRANICZENIA INTERFEJSY SZABLONY safa Michał Telus.
1 Strumienie Hierarchie klas strumieniowych, strumienie bajtowe - klasy InputStream i OutputStream i ich metody, klasa File, strumienie plikowe, strumienie.
Kurs języka C++ – wykład 13 ( )
Wykład 7 Synchronizacja procesów i wątków
Kurs języka C++ – wykład 9 ( )
Podstawy języka Instrukcje - wprowadzenie
Programowanie strukturalne i obiektowe C++
Zmienne i typy danych w C#
Kurs języka C++ – wykład 4 ( )
Technologie internetowe Wykład 5 Wprowadzenie do skrytpów serwerowych.
Paweł Starzyk Obiektowe metody projektowania systemów
Łukasz Bieszczad Mateusz Gałązka Karol Włodarek
Programowanie Zaawansowane
Zestaw pytań nr. 3 Typy generyczne Wyjątki OPRACOWALI: JAKUB GRYCZEWSKIKINGA ROSA DANIEL KAPTEJNYWOJCIECH ŁĘCZYCKI
Podstawy informatyki Tablice Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego Matuszyka Podstawy.
K URS JĘZYKA C++ – WYKŁAD 3 ( ) Przenoszenie Składowe statyczne Funkcje wbudowane Argumenty domyślne.
P ASCAL Definicje, deklaracje, podstawowe instrukcje 1.
Programowanie Obiektowe – Wykład 6
Typy wyliczeniowe, kolekcje
(według:
Delegaty Delegat to obiekt „wiedzący”, jak wywołać metodę.
Programowanie Obiektowe – Wykład 2
Język C++ Typy Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego.
PGO - Projektowanie i implementacja pierwszych klas
PGO Dziedziczenie Michail Mokkas.
PGO Porównywanie obiektów
Zapis prezentacji:

Programowanie komponentowe jesień-zima 2013 Wykład 3 Metody wstrzykiwania zależności dr inż. Wojciech Bieniecki Instytut Nauk Ekonomicznych i Informatyki http://wbieniec.kis.p.lodz.pl/pwsz

Rozwiązywanie zależności komponentów Metoda tradycyjna polega na aktywnym wyszukiwaniu instancji komponentów w rejestrze kontenera. Metoda nowoczesna wstrzykiwanie zależności (ang. dependency injection). Sposoby wstrzykiwania zależności Interface injection - wstrzykiwanie przez interfejs. Komponenty implementują dedykowany interfejs, poprzez który otrzymują obiekt służący do wyszukiwania zależności Constructor injection wstrzykiwanie przez konstruktor. Wszystkie zależności komponentu muszą zostać spełnione w momencie jego tworzenia, a ich rozwiązaniem i spełnieniem zajmuje się kontener. Setter injection wstrzykiwanie przez właściwości obiektu, czyli przekazanie przez kontener referencji do zależnego komponentu przez metody typu setXXX()

Wstrzykiwanie zależności przez interfejs Obiekt wyszukuje zależności poprzez obiekt kontekstu, przekazany jako parametr metody zdefiniowanej w interfejsie Jest to najpopularniejsza metoda rozwiązywania zależności (np. w J2EE mechanizm JNDI lub Naming Service w CORBA). Metoda polega na implementacji w komponencie interfejsu, stanowiącego znacznik wskazujący, że komponent ten wymaga pewnych zależności. Interfejs deklaruje metodę posiadającą parametr, który jest obiektem kontekstu – wyszukiwarką innych obiektów. Komponent w momencie utworzenia otrzymuje od kontenera instancję kontekstu, którą może zapamiętać, a następnie wykorzystać do rozwiązania swoich zależności. Wady: silne powiązanie z konkretnym kontenerem, jakie wynika z konieczności implementacji przez komponent. Gdy dostępny jest jedynie komponent w wersji binarnej – użycie tego sposobu jest niemożliwe. Zalety: • odsunięcie w czasie rozwiązywania zależności • obsługa zależności cyklicznych • łatwe testowanie

Wstrzykiwanie przez interfejs public interface Serviceable { public void service(ServiceManager manager); } public class Samochod implements Serviceable { private ServiceManager manager = null; private Silnik silnik = null; public void service(ServiceManager manager) { this.manager = manager; this.silnik = (Silnik) manager.lookup("Silnik"); Klasa Samochód deklaruje implementację interfejsu Serviceable. Interfejs ten definiuje metodę service(), przyjmującą parametr typu ServiceManager pełniący rolę obiektu-kontekstu Parametr ten zostanie przekazany komponentowi przez kontener w momencie jego tworzenia poprzez wywołanie metody service(). Obiekt ServiceManager jest wyszukiwarką instancji komponentów w rejestrze kontenera poprzez metodę lookup(), która wyszukuje w rejestrze komponent po nazwie. Komponent Samochód może uzyskać referencję do zależnego komponentu Silnik. WADA: Komponent musi wywołać lookup sam. Rola kontenera ogranicza się do utrzymywania rejestru komponentów i dostarczenia obiektu kontekstu

Wstrzykiwanie zależności przez konstruktor Obiekt otrzymuje wszystkie zależności w postaci parametrów konstruktora Komponent nie musi sam zdobywać zasobów. Komponent deklaruje potrzebę ich wykorzystania w sposób, który jest czytelny dla kontenera i pozwala mu rozwiązać zależności. Odpowiedzialność za dostarczenie zależności jest przeniesiona na kontener. Deklaracja zależności odbywa się poprzez parametry konstruktora Kontener dostarcza obiekty poprzez implementacje tych parametrów Jeżeli korzystając z zarejestrowanych komponentów nie można tego uczynić, utworzenie komponentu zależnego nie jest możliwe i zgłaszane w postaci wyjątku. W przypadku gdy komponent posiada wiele konstruktorów, kontenery próbują utworzyć go korzystając z konstruktora najbardziej specyficznego (tj. o najdłuższej liczbie parametrów), którego zależności mogą rozwiązać.

Wstrzykiwanie zależności przez konstruktor ZALETA: Zapewnienie spójnego stanu komponentu w każdym momencie jego istnienia (co jest jednym z warunków tzw. dobrego obywatelstwa), także bezpośrednio po wywołaniu konstruktora przez komponent. WADA: brak możliwości zrealizowania zależności cyklicznych, tj. takich, w których komponenty zależą od siebie wzajemnie. PRZYKŁAD: W kodzie programu mechanizm ten wymaga jedynie stworzenia w klasie komponentu Samochód konstruktora przyjmującego obiekt o interfejsie Silnik jako parametr. Kontener, tworząc instancję klasy Samochód, musi najpierw utworzyć obiekt typu Silnik, aby przekazać go do właściwego konstruktora. public class Samochod { private Silnik silnik = null; public Samochod(Silnik silnik) this.silnik = silnik; }

Wstrzykiwanie zależności przez właściwości Komponent jedynie deklaruje zależności, spełnieniem zajmuje się kontener Do przekazania instancji obiektów zależnych używamy metod, tzw setterów. Zalety • odsunięcie w czasie rozwiązywania zależności (komponent można skonfigurować dopiero przed samym użyciem) • możliwość obsługi zależności cyklicznych (nie było to możliwe w poprzedniej metodzie) • łatwe testowanie Wada: • stan niespójny po utworzeniu – obiekt nie jest w pełni zainicjowany. Wprawdzie proces ten zwykle jest realizowany przez kontener, który zapewnia poprawność komponentu w momencie jego wykorzystania, jednak w szczególnych okolicznościach może to spowodować nieprawidłowe zachowanie programu.

Wstrzykiwanie zależności przez właściwości public class Samochod { private Silnik silnik = null; public Samochod() { } public void setSilnik(Silnik silnik) { this.silnik = silnik; Klasa Samochód posiada bezparametrowy konstruktor oraz metodę setSilnik(), która przyjmuje obiekt typu Silnik jako argument. Kontener wywoła tę metodę na komponencie, pozwalając mu zapamiętać referencję do przekazanego w postaci parametru obiektu.

Konfiguracja rejestru kontenera w Spring W Java Spring komponenty konfigurujemy w pliku applicationContext.xml <beans> <!-- wstrzykiwanie przez konstruktor --> <bean id="samochod1" class="lab.Samochod"> <constructor-arg> <ref bean="silnik"/> </constructor-arg> </bean> <!-- wstrzykiwanie przez właściwość --> <bean id="samochod2" class="lab.Samochod"> <property> </property> <bean id="silnik" class="lab.Silnik1_6"/> </beans> Plik definiuje dwa komponenty typu Samochód. Komponent dostępny pod nazwą samochod1 wykorzystuje wstrzyknięcie komponentu Silnik przez konstruktor, natomiast pod nazwą samochod2 znajduje się komponent korzystający z wstrzykiwania przez właściwość o nazwie silnik.

Programowanie w C# - część 2

Zmienne w C# Non-nullable value type Wartość zdefiniowanego typu, np. int, float Nullable value type Wartość zdefiniowanego obiektu oraz null, np.: Nullable<Int32> oznacza liczby typu Int32 (4 bajty ze znakiem) oraz null object null, referencja do obiektu dowolnego typu, referencja do boxowanej wartości dowolnego typu Klasa Null, referencja do instancji klasy, referencja do instancji klasy dziedziczącej Interfejs Null, referencja do instancji klasy implementującej interfejs, referencja do boxowanej wartości typu implementującego interfejs Tablica Null, referencja do instancji tablicy danego lub kompatybilnego typu Delegat Null, referencja do instancji typu delegata

Typy referencyjne i wartościowe Dla typów referencyjnych przydzielane są obszary pamięci na zarządzanej stercie, typy wartościowe są inicjalizowane zerami. Zwalnianie pamięci – pamięć na stosie jest zwalniania w momencie, w którym dana zmienna opuszcza bieżący zakres przetwarzania. Zwalnianie pamięci na stercie – odpowiada proces odzyskiwania pamięci (sprawdzany jest licznik referencji) 123 i s "Hello world" int i = 123; string s = "Hello world"; Zmienne wartości - bezpośrednio zawierają dane Każda zmienna typu wartości reprezentuje oddzielny obszar pamięci, dlatego operacja na jednej zmiennej nie wpływa na drugą. Zmienne lokalne przechowywane w obszarze pamięci zwanym stosem. Z miejscem przechowywania i sposobem zarządzania tym obszarem związany jest czas życia zmiennej. Czas życia zmiennej możemy zdefiniować jako czas, przez który jest zarezerwowana pamięć dla zmiennej. Pamięć jest zarezerwowana dla zmiennej lokalnej od miejsca jej zadeklarowania do końca bloku, w którym została zadeklarowana. Przed użyciem zmienna musi być zainicjalizowana - musi mieć nadaną wartość.

Typy nullable Dla wszystkich typów wartości wprowadzono pewną formę typu (nullable types), której zmienne mogą przyjmować wartości null (wartość nieokreślona). Typy nullable wprowadzono, aby ułatwić współpracę z bazami danych. class NullableExample { static void Main() { int? num = null; if (num.HasValue) System.Console.WriteLine("num = " + num.Value); else System.Console.WriteLine("num = Null"); int y = num.GetValueOrDefault(); try { y = num.Value; } catch (System.InvalidOperationException e){ System.Console.WriteLine(e.Message);

Boxowanie 123 i int i = 123; object o = i; int j = (int)o; 123 o System.Int32 123 j W języku C# istnieje jeszcze standardowa konwersja - opakowanie (boxing). Opakowanie wartości polega na niejawnym przekształceniu typu wartości w typ object. Rozpakowanie (unboxing) musi być jawne i może powodować wyjątek. int i = 123; object o = i; // implicit boxing try { int j = (short)o; // attempt to unbox System.Console.WriteLine("Unboxing OK."); } catch (System.InvalidCastException e) { System.Console.WriteLine("{0} Error: Incorrect unboxing.", e.Message);

Typ wbudowany string Łańcuchy : public sealed class String : IComparable, ICloneable, IConvertible, IEnumerable{ public char this[int index] {get;} public int Length {get;} public static int Compare(string strA, string strB); public static int CompareOrdinal(string strA, string strB); public static string Format(string format, object arg0); public int IndexOf(string); public int IndexOfAny(char[] anyOf); public int LastIndexOf(string value); public string PadLeft(int width, char c); public string[] Split(params char[] separator); public string Substring(int startIndex, int length); ... } Łańcuchy : łańcuch jest sekwencją wartości typu char porównywane są według wartości niezmienne (ang. immutable) – zmodyfikowane są zapisywane pod innymi adresami niż oryginalne string s = "Hi there."; Console.WriteLine( "{0}", s.ToUpper() ); // Print uppercase copy Console.WriteLine( "{0}", s ); // String is unchanged

Przykłady testowania stringów string s1 = "Hello!"; string s2 = "Yo!"; Console.WriteLine("s1 = {0}", s1); Console.WriteLine("s2 = {0}", s2); Console.WriteLine(); // UWAGA == porównuje referencje a nie obiekty! Console.WriteLine("s1 == s2: {0}", s1 == s2); Console.WriteLine("s1 == Hello!: {0}", s1 == "Hello!"); Console.WriteLine("s1.Equals(s2): {0}", s1.Equals(s2)); Console.WriteLine("Yo.Equals(s2): {0}", "Yo!".Equals(s2));

Podstawowe operacje na łańcuchach Metody Opis Compare() porównanie dwóch łańcuchów Equals() Czy łańcuchu mają tę samą zawartość Concat() utworzenie nowego łańcucha z jednego lub większej liczby Copy() utworzenie nowego łańcucha przez przekopiowanie zawartości Chars[] indekser łańcucha Insert() zwraca nowy łańcuch z dostawionym nowym łańcuchem Remove() usunięcie z łańcucha określonej liczby znaków Split() rozbicie łańcucha na podłańcuchy przy założonym zbiorze ograniczników StartsWith() wskazuje czy łańcuch rozpoczyna się od określonych znaków Substring() wyłuskanie podłańcucha ToLower() zwraca kopię łańcucha składającego się z małych liter Trim() wyrzucenie określonego zbioru znaków z początku i końca łańcucha

Znaki specjalne w łańcuchach Łańcuchy standardowe i dosłowne (ang. verbatim) string rst1 = "Hi there!"; string vst1 = @"Hi there!"; string rst2 = "It started, \"Four score and seven...\""; string vst2 = @"It started, ""Four score and seven..."""; string rst3 = "Value 1 \t 5, Val2 \t 10"; string vst3 = @"Value 1 \t 5, Val2 \t 10"; string rst4 = "C:\\Program Files\\Microsoft\\"; string vst4 = @"C:\Program Files\Microsoft\"; string rst5 = " Print \x000A Multiple \u000A Lines"; string vst5 = @" Print Multiple Lines";

Łańcuchy zmienne - StringBuilder StringBuilder myBuffer = new StringBuilder ("Ala ma kota"); myBuffer.Append(" a Ola psa."); myBuffer.Insert(11, ','); string Ready = myBuffer.ToString(); // Ala ma kota, a Ola psa. Klasa System.Text.StringBuilder konstruowanie i przetwarzanie łańcuchów składowanych w buforze bardziej efektywne w przetwarzaniu łańcuchów public sealed class StringBuilder { public int Capacity {get; set;} public int Length {get; set;} StringBuilder Append(...); StringBuilder AppendFormat(...); StringBuilder Insert(int index, ...); StringBuilder Remove(int startInd, int len); StringBuilder Replace(char oldCh, char newCh); string ToString(); }

Typ wyliczeniowy – System.Enum Typy zawierające zbiór nazwanych stałych Łatwiejsze czytanie kodu – przypisanie łatwo identyfikowalnych nazw do wartości; Łatwość pisania kodu – IntelliSense podpowiada listę możliwych wartości; Łatwość utrzymania kodu - pozwala zdefiniować zbiór stałych i zadeklarować zmienne, które będą akceptować wartości tylko z tego zbioru Definiuje się go przy pomocy słowa kluczowego enum, po którym występuje nazwa nowego typu, a następnie w nawiasach klamrowych podajemy nazwy symboliczne dopuszczalnych wartości, oddzielone przecinkami. Można również przypisać w sposób jawny wartości poszczególnym elementom np.: enum Kolory{czerwony=4, zielony, niebieski=7}; Element zielony ma w sposób niejawny przypisaną wartość 5. Przy definicji typu wyliczeniowego można podać, jaki typ całkowity jest typem bazowym dla definiowanego typu wyliczeniowego. Typem bazowym może być dowolny tym całkowity poza typem char. enum PoryRoku : byte {Wiosna, Lato, Jesien, Zima};

System.Enum – przykład enum Color { Red, Green, Blue }; Color a = Color.Red; Color b = Color.Green; Color c = Color.Blue; Console.WriteLine("Wartości typu Color: "); foreach(string s in Enum.GetNames(typeof(Color))) Console.WriteLine(s); Console.WriteLine("Blue należy do typu Color ?: {0}", Enum.IsDefined(typeof(Color),"Blue")); Console.WriteLine("Yellow należy do typu Color ?: {0}", Enum.IsDefined(typeof(Color), "Yellow"));

Tablice w C# Cechy tablicy: jednorodność - jest złożona z elementów tego samego typu zwanego typem podstawowym tablicy swobodny dostęp - wszystkie elementy tablicy są jednakowo dostępne - w dowolnej kolejności i w jednakowym czasie stała (niezmienna) ilość elementów ciągłość - zajmuje ciągły obszar pamięci Pojedynczy element dostępny za pomocą indeksu typ [] nazwa; // Deklaracja zmiennej tablicowej nazwa = new typ[liczba_Elementow]; //utworz. obiektu tablicowego typ2 [] nazwa2 = new typ2[ilosc_Elementow2]; //deklar. z definicją int[] tab1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Wbudowane operacje na tablicach Kopiowanie wartości elementów jednej tablicy do drugiej tablicy. int[] tab1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int[] tab2 = {11,12,13,14,15,16,17,18,19 }; Array.Copy(tab1,2,tab2,4,4); tab2: {11, 12, 13, 14, 3, 4, 5, 6, 19,} Skopiowanie wartości jednej zmiennej tablicowej do drugiej zmiennej tablicowej, spowoduje że obie zmienne tablicowe będą odwoływać się do tego samego obiektu tablicowego. Sortowanie tablicy int[] tab1 = { 4, 1, 83, 41, 53, 36, 47, 18}; Array.Sort(tab1); tab1: {1, 4, 18, 36, 41, 47, 53, 83,} Inne operacje: Reverse – odwracanie kolejności tablicy lub jej fragmentu Exists, FindLast, FindAll, FindIndex, FindLastIndex – przeszukiwanie tablicy lub jej fragmentu