Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Programowanie komponentowe jesień-zima 2013

Podobne prezentacje


Prezentacja na temat: "Programowanie komponentowe jesień-zima 2013"— Zapis prezentacji:

1 Programowanie komponentowe jesień-zima 2013
Wykład 4 Cykl życia komponentu Wzorce projektowe Programowanie obiektowe w C# dr inż. Wojciech Bieniecki Instytut Nauk Ekonomicznych i Informatyki

2 Cykl życia komponentu Każdy komponent jest zarządzany przez kontener.
W czasie swojego życia, komponent może jednak mieć wpływ na swoją inicjalizację, konfigurację i usuwanie. Jest to możliwe dzięki temu, że istnieje kontrakt kontrakt pomiędzy komponentem deklarującym określone metody odpowiadające tym etapom, a kontenerem, który we właściwym momencie je wywoła. Komponent nie ma możliwości wpływania na kolejność ani moment wywoływania tych procedur

3 Reprezentacje cyklu życia komponentu
1. Poprzez specjalizowane interfejsy związane z danym kontenerem, które definiują metody reprezentujące poszczególne etapy życia komponentu • silne powiązanie z kontenerem • duża liczba interfejsów 2. Poprzez bezpośrednie podanie nazw metod związanych z konkretną fazą życia komponentu podczas jego konfiguracji. • elastyczne • bardzo prosty mechanizm konfiguracji

4 Cykl życia definiowany przez interfejs
1. konstruktor 2. contextualize() 3. compose() 4. configure() 5. parametrize() 6. initialize() 7. start() INICJALIZACJA 1.suspend() 2. recontextualize() 3. recompose() 4. reconfigure() 5. reparametrize() 6. resume() OBSŁUGA ŻĄDAŃ 1. stop() 2. dispose() 3. finalizacja USUNIĘCIE Przykład - kontener Apache Avalon Fortress. Duża liczba możliwych do wywołania metod – programista może uwzględnić każdy etap w cyklu życia komponentu. Wada – konieczność implementacji wielu interfejsów związanych z konkretnym kontenerem

5 Cykl życia definiowany przez nazwy metod
Rozwiązanie to daje ono potencjalnie większe możliwości konfiguracji komponentu. Polega na określaniu nazw metod wywoływanych w typowych fazach życia komponentu i przekazaniu ich kontenerowi w postaci konfiguracji. Przykład – Spring. komponent Ksiazka posiada metodę inicjuj() wywoływaną tuż po utworzeniu instancji obiektu oraz metodę usun() wykonywaną przed usunięciem instancji komponentu z rejestru. <bean id="Ksiazka" class="elearning.Ksiazka" init-method="inicjuj" destroy-method="usun"> <property name="karta" /> </bean>

6 Styl życia komponentu Liczba instancji komponentu
prototyp: każde żądanie tworzy nową instancję Kontener tworzy komponenty-wartości – instancje są tworzone w odpowiedzi na każde żądanie. singleton: istnieje jedna współdzielona instancja Kontener tworzy komponenty-referencje (podobne do obiektów-referencji), których jedyna instancja jest współdzielona przez wszystkich żądających do niej dostępu klientów. Moment tworzenia komponentu • eager (zachłanny): przy starcie kontenera • lazy (leniwy): gdy będzie potrzebny

7 Dygresja – wzorce projektowe
Wzorzec projektowy (design pattern) – w inżynierii oprogramowania, uniwersalne rozwiązanie powtarzalnych problemów projektowych. Pokazuje powiązania i zależności pomiędzy klasami oraz obiektami i ułatwia tworzenie, modyfikację oraz pielęgnację kodu źródłowego. Jest opisem rozwiązania. Kreacyjne – opisują proces tworzenia, inicjalizacji i konfiguracji nowych obiektów. Przykłady: Budowniczy, Fabryka abstrakcyjna, Metoda wytwórcza, Prototyp, Singleton strukturalne – opisują struktury powiązanych ze sobą obiektów; Przykłady: Adapter, Dekorator, Fasada, Kompozyt, Most, Pełnomocnik, Pyłek. czynnościowe – opisują zachowanie współpracujących ze sobą obiektów. Przykłady: Interpreter, Iterator, Łańcuch zobowiązań, Mediator, Metoda szablonowa, Obserwator, Odwiedzający, Pamiątka, Polecenie, Stan, Strategia

8 Przykłady wzorców projektowych - Singleton
Singleton to obiekt, który może istnieć tylko w jednej instancji (tak jak np. obiekt aplikacji w aplikacji MFC lub obiekt Servletu w kontenerze serwletów. Implementacja: Statyczna metoda getInstance. Sprawdza, czy istnieje już instancja tej klasy, w razie potrzeby tworząc ją. Następnie instancja zwracana jest przez referencję. Instancję przechowuje się w prywatnym statycznym polu klasy. Konstruktor klasy jest prywatny – nie można go wywołać operatorem new Przykład w C# sealed class Singleton { private static readonly Singleton instance = new Singleton(); private Singleton() { / * pusty konstruktor prywatny */ } static Singleton() { /* pusta metoda statyczna */ } public static Singleton Instance { /* metoda getInstance */ get { return instance; }

9 Przykłady wzorców projektowych – Adapter
Adapter o obiekt, który implementuje w sposób domyślny (lub pusty) wszystkie metody Interfejsu, dzięki czemu łatwiej jest napisać klasę obsługującą ten interfejs. Przykład w Java – obsługa myszy public interface MouseListener extends EventListener { public void mouseClicked(MouseEvent e); public void mousePressed(MouseEvent e); public void mouseReleased(MouseEvent e); public void mouseEntered(MouseEvent e); public void mouseExited(MouseEvent e); } public abstract class MouseAdapter implements MouseListener { public void mouseClicked(MouseEvent e) {} public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} }

10 Przykłady wzorców projektowych – Adapter
public class MyApp1 implements MouseListener { JFrame f = new Jframe("Hello"); MyApp1(){ f.setVisible(true); f.addMouseListener(this); } public void mouseClicked(MouseEvent e) { f.setBackground(Color.red); public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public class MyApp2 extends MouseAdapter{ JFrame f = new Jframe("Hello"); MyApp2(){ f.setVisible(true); f.addMouseListener(this); } public void mouseClicked(MouseEvent e) { f.setBackground(Color.red);

11 Przykłady wzorców projektowych – obserwator
Obserwator to obiekt, który raportuje zmiany stanu obiektu obserwowanego. Działa tak, że zmiana w obiekcie obserwowanym wywołuje specyficzne zdarzenia, na które możemy reagować. Przykład – użycie obiektu ImageObserwer w Javie, pozwalającego obserwować proces ładowania obrazu Aby obserwować ładowanie obrazka, należy zdefiniować metodę imageUpdate(...) interfejsu ImageObserver. Każdy komponent jest z natury ImageObserverem. Metoda imageUpdate jest wołana za każdym razem, gdy informacja o obrazie jest dostępna. Uzyskuje ona tę informację w postaci infoflag. Wartość Stała Opis 128 ABORT Proces ładowania obrazka został przerwany 64 ERROR Napotkano błąd w czasie odczytu obrazu 1 WIDTH Odczytano szerokość obrazu 2 HEIGHT Odczytano wysokość obrazu 8 SOMEBITS Część obrazu została załadowana (w przypadku progresywnych obrazków) 16 FRAMEBITS Załadowano następną ramkę obrazu (w przypadku obrazu wieloramkowego) 32 ALLBITS Wszystkie bity obrazka zostały załadowane. Można wyświetlić obraz w ostatecznej formie

12 Użycie obiektu ImageObserver
Aby obserwować ładowanie obrazka, należy zdefiniować metodę imageUpdate(...) interfejsu ImageObserver. Każdy komponent jest z natury ImageObserverem. Metoda imageUpdate jest wołana za każdym razem, gdy informacja o obrazie jest dostępna. Uzyskuje ona tę informację w postaci infoflag. import javax.swing.*; class Kanwa extends JPanel { Image img; String itit; int width, height; boolean imageReady = false, imageError = false, firstPaintDone = false; Kanwa (String s,Image im, int w, int h) itit=s; img = im; width = w; height = h; }

13 Użycie obiektu ImageObserver
public boolean imageUpdate(Image theImg, int Infoflags, int x, int y, int w,int h) { if (infoflags & (ERROR)) != 0) ImageError=true; else if ((infoflags & (WIDTH | HEIGHT)) != 0) width = w; height = h; } imageReady=((infoflags & (ERROR|FRAMEBITS|ALLBITS)) != 0); if (imageReady) repaint(); return !imageReady; Ta metoda jest automatycznie wywoływana przez proces ładowania obrazu i program może odczytywać stan obiektu (tu: aktualizować zmienne imageReady, width oraz height)

14 Przykłady public void paint(Graphics g) { int w = getSize().width;
int h = getSize().height; g.setFont(new Font("Helvetica", Font.BOLD, 14)); g.drawRect(0, 0, w-1, h-1); g.drawLine(0,30, w-1,30); g.drawLine(0, h-40 , w, h-40); g.drawString(name,(w-g.getFontMetrics().stringWidth(name))/2,20); String s = "Gotowe!"; if (!imageReady){ s = "Czekaj ... "; g.drawString(s,(w - g.getFontMetrics().stringWidth(s))/2,h-10); } else { if (imageError) s = "Wadliwy obrazek!"; if (!firstPaintDone){ ((JFrame) getParent()).pack(); firstPaintDone = true; } if (!imageError) g.drawImage(img, 5, 40, w-10, h-90, this);

15 Przykłady wzorców - Budowniczy
Budowniczy (Builder) – element programowania komponentowego. Obiekt, który konstruuje inny obiekt (najczęściej kilkuetapowo, gdyż złożony jest z mniejszych komponentów). Rozdziela algorytm tworzenia obiektu od reprezentacji obiektów. Różne warianty omawianego wzorca wykorzystywane są w bibliotece MFC, implementując architekturę dokument/widok. Obiekt klasy CDocument oraz jego podobiekty tworzone są poprzez wywołanie metody tworzącej z trzema parametrami typu CRuntimeClass. Klasa ta zawiera metodę CreateObject, umożliwiającą jej tworzenie obiektów różnych klas (m.in. CDocument, CFrameWnd oraz CView). Dzięki takiemu zachowaniu CRuntimeClass może być nazwana klasą Budowniczego. //Przykład tworzenia pizzy wC#. class Pizza { string ciasto; string wierzch; string sos; public string Ciasto {get{return ciasto;}set{ciasto=value; } } public string Wierzch {get{return wierzch;}set{wierzch=value; } } public string Sos {get{return sos;}set{sos=value; } } public override string ToString() { return string.Format( "Pizza z ciasta {0}, z sosem {1} i wierzchem {2}", Ciasto, Sos, Wierzch); }

16 Przykłady wzorców - Budowniczy
//Budowniczy abstrakcyjny abstract class PizzaBuilder { protected Pizza pizza; public Pizza Pizza { get { return pizza; } } public void CreateNewPizza() { pizza = new Pizza(); } public abstract void BudujCiasto(); public abstract void BudujSos(); public abstract void BudujWierzch (); } //Budowniczy konkretny class Hawajska_PizzaBuilder : PizzaBuilder { public override void BudujCiasto() { pizza.Ciasto = "grube"; } public override void BudujSos() { pizza.Sos = "majonez"; } public override void BudujWierzch() { pizza.Wierzch = "szynka/ananas"; } } //Budowniczy konkretny class Pikantna_PizzaBuilder : PizzaBuilder { public override void BudujCiasto() { pizza.Ciasto = "cienkie"; } public override void BuildSos() { pizza.Sos = "ostry ketchup"; } public override void BuildWierzch() { pizza.Wierzch = "pepparoni+salami"; } }

17 Przykłady wzorców - Budowniczy
class Kucharz { private PizzaBuilder pizzaBuilder; public PizzaBuilder PizzaBuilder { get { return pizzaBuilder; } set { pizzaBuilder = value; } } public Pizza Pizza { get { return pizzaBuilder.Pizza; } } public void ConstructPizza() { pizzaBuilder.CreateNewPizza(); pizzaBuilder.BudujCiasto(); pizzaBuilder.BudujSos(); pizzaBuilder.BudujWierzch(); } } public class TestPizza { private static void BuildAndDisplayPizza(Kucharz k) { k.ConstructPizza(); System.Console.WriteLine(k.Pizza); public static void Main() { Kucharz k = new Kucharz(); k.PizzaBuilder = new Hawajska_PizzaBuilder(); BuildAndDisplayPizza(k); k.PizzaBuilder = new Pikantna_PizzaBuilder(); BuildAndDisplayPizza(k); } }

18 Budowniczy a Fabryka obiektów
W przypadku korzystania z Budowniczego obiekt może być budowany „na raty”. Budowniczy udostępnia kilka metod, którymi stopniowo buduje obiekt. Porównaj StringBuilder. Fabryka zwraca nam gotowy obiekt przy jednym wywołaniu. Przykład – Java – Zakładamy istnienie fabryki abstrakcyjnej i fabryk konkretnych (dla poszczególnych platform systemowych. Fabryka tworzy obiekty – przyciski. abstract class GUIFactory { public static GUIFactory getFactory() int sys = readFromConfigFile("OS_TYPE"); if (sys == 0) return new WinFactory(); else return new OSXFactory(); } public abstract Button createButton();

19 Fabryka obiektów class WinFactory extends GUIFactory {
public Button createButton() { return new WinButton(); } } class OSXFactory extends GUIFactory { public Button createButton() { return new OSXButton(); } } abstract class Button { public abstract void paint(); } class WinButton extends Button { public void paint() { System.out.println("Przycisk WinButton"); } } class OSXButton extends Button { public void paint() { System.out.println("Przycisk OSXButton"); } } public class Application { public static void main(String[] args) { GUIFactory factory = GUIFactory.getFactory(); Button button = factory.createButton(); button.paint(); }

20 Dekorator Klasę możemy wzbogacić poprzez dziedziczenie. Można to robić na etapie kompilacji. Dekorator pozwala na wzbogacenie istniejącego w pamięci obiektu nie naruszając stanu obiektu. Obiekt można dekorować wielokrotnie i w dowolnej kolejności Przykład w Javie – obsługa strumieni File plik = new File("test.txt"); //Otwieramy plik // dekorujemy plik, jako strumień wejściowy FileInputStream fstream = new FileInputStream(plik); // dekorujemy strumień – odczyt liczb zapisanych binarnie DataInputStream in = new DataInputStream(fstream); //ponowna dekoracja – umożliwia zmianę kodowania bajty na znaki InputStreamReader is = new InputStreamReader(in); //ponowna dekoracja – umożliwia odczyt linia po linii   BufferedReader br = new BufferedReader(is);

21 Dekorator – implementacja
Zwykle dekorator implementujemy jako klasę dziedziczącą po udekorowanej klasie, zawierającą dodatkowo wskaźnik (lub referencję) na dekorowany obiekt /** Klasa, którą będziemy dekorować */ public class Book{ String author; String title; int pages; public String toString(){ return ("|" + author + "|" + title + "|" + pages + "|"); } public Book(String author, String title, int pages){ this.author = author; this.title = title; this.pages = pages; public String getAuthor(){return author;} public String getTitle() {return title; } public int getPages() {return pages; }

22 Dekorator – implementacja
/** abstrakcyjny dekorator */ public abstract class CoverIndex extends Book{ protected Book decorBook; //referencja na obiekt public CoverIndex(Book decorBook) { this.decorBook = decorBook;} } public class CoverClassic extends CoverIndex{ public CoverClassic(Book decorBook){super(decorBook);} public String toString(){ return decorBook.toString() + "| Classic Cover"; } } public class CoverHard extends CoverIndex{ public CoverHard(Book decorBook){super(decorBook);} public String toString(){ return decorBook.toString() + "| Hard Cover"; } } public class CoverDecorative extends CoverIndex{ public CoverDecorative(Book decorBook){super(decorBook);} public String toString(){ return decorBook.toString() + "| Decorative Cover"; } }

23 Dekorator – implementacja
class Main{ public static void main(String args[]) { Book b = new Book("Mickiewicz" , "Dziady", 300); b = new CoverDecorative(b); //Dekoracja w oprawę ozdobną b = new CoverHard(b); //dekoracja w oprawę twardą System.out.println(b); // Mickiewicz | Dziady | 300 | Decorative Cover | Hard Cover }

24 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.

25 Programowanie w C# - część 3

26 Właściwości klasy Console:
Użycie konsoli Metody klasy Console: Beep Gra sygnał poprzez głośnik konsolowy. Clear Czyści bufor konsoli i odpowiadające mu okno. ResetColor przywraca domyślne kolory czcionki i tła dla konsoli SetCursorPosition – ustawia kursor na podanej pozyji SetWindowPosition – ustawia pozycję okna konsolowego. SetWindowSize – ustawia szerokość i wysokość okienka konsolowego (liczba wierszy i kolumn) Właściwości klasy Console: Console.Title = "Hello World"; Console.BackgroundColor = ConsoleColor.DarkYellow; bool Console.GetCapsLock(); sprawdza czy jest wciśnięty klasisz CapsLock In Console.GetCursorSize(); //wyświetla wielkość kursora w procentach wielkości komórki

27 Zasady obiektowości w C#
Większość zasad tworzenia i używania klas jest taka sama jak w Javie lub C++ Korzystanie z obiektu. W C# tak jak w Javie, wszystkie metody oraz zmienne muszą być składowymi klas lub struktur. Obiekt tworzymy poprzez operator new. Nie ma operatora delete, ani destruktora. Każdy obiekt dziedziczy z object Klasa1 zmienna1 = new Klasa1(); Odwołanie się do składowych (czyli metod, zmiennych lub właściwości zmienna1.X = 20; //odwołanie się do pola (lub właściwości zmienna1.Metoda1(); //wywołanie metody Ukrywanie informacji – modyfikatory dostępu private Dostępne tylko z metod danej klasy public Ogólnie dostępne protected dostępne dla klas i potomków klasy internal dostęp dla klas z pakietu internal protected dostęp dla klas z pakietu lub potomnych Metody klasy object ToString - domyślna wersja tej metody zwraca w pełni kwalifikowaną nazwę klasy Equals - domyślnie porównuje referencje GetHashCode – wartość skrótu dla obiektu

28 Zasady obiektowości w C#
Właściwości (Properties) Właściwość to metoda składowa klasy, wraz z elastycznym mechanizmem odczytu, zapisu i przetwarzania prywatnego pola klasy class Prostokat{ private int a; private int b; public int A{ get{ return a; } set{ a = (value>0?value:0);} } public int B{ get{ return b; } set{ b = (value>0?value:0);} public int P{ get { return a*b; } A, B i P to są właściwości klasy Prostokąt. Używamy ich tak jakby to były pola klasy, w rzeczywistości są to metody Prostokat pr = new Prostokat(); pr.A = 10; pr.B = 20; Console.writeln("Dane prostokąta A={0}, B={1}, pole={2}", pr.A, pr.B, pr.P); Właściwości to bezpieczne akcesory (settery, gettery), które w kontrolowany sposób dają dostęp do pól prywatnych, jednocześnie tak łatwe w użyciu jak pola

29 Właściwości automatycznie implementowane
Gdy deklarujesz właściwości tak, jak w poniższym przykładzie kompilator sam tworzy prywatne anonimowe pola, do których dostęp możliwy jest poprzez akcesory get i set. class Klient{ public double SumaZakupow{ get; set; } public string Nazwisko { get; set; } public int IdKlienta {get; set; } Klient(double zakupy, string nazwisko, int id) { SumaZakupow = zakupy; Nazwisko = nazwisko; IdKlienta = id; }

30 Indekser Indeksery to właściwości sparametryzowane definiowane wewnątrz klas Indekser może otrzymywać na wejściu jeden lub wiele parametrów, a nazwa indeksera jest reprezentowana prze słowo kluczowe this. Oferuje sposób dostępu do kolekcji wartości utrzymywanych w ramach pojedynczego obiektu klasy (jest to odpowiednik przeciążonego operatora indeksowania w C++) public class TablicaKsiazek { Ksiazka[] ksiazki; public Ksiazka this [int index] { get { return ksiazki[index]; } set { if (value!=null) { ksiazki[index] = value; } TablicaKsiazek polka = new TablicaKsiazek(); polka[155] = new Ksiazka("Pan Tadeusz"); polka[0] = new Ksiazka("Dziady");

31 Klasy wieloplikowe W C# definicja klasy nie musi znajdować się w całości w jednym pliku Załóżmy, że jeden plik z definicją klasy jest do naszej dyspozycji i możemy dodawać tam własny kod, drugi jest uaktualniany przez środowisko Visual Studio i nie powinniśmy go modyfikować. Drugie zastosowanie – praca grupowa Obie części będą tworzyły jedną klasę pod warunkiem, że będą miały tę samą, w pełni kwalifikowaną nazwę, czyli będą znajdować się w tej samej przestrzeni nazw. Wszystkie części muszą być dostępne w czasie kompilacji – nie możemy w ten sposób rozszerzać klas już skompilowanych. //Plik1.cs partial class Klasa1 { //częściowa definicja klasy } //Plik2.cs partial class Klasa1 { //częściowa definicja klasy }


Pobierz ppt "Programowanie komponentowe jesień-zima 2013"

Podobne prezentacje


Reklamy Google