Celem tego laboratorium jest poznanie i praktyczne zastosowanie wzorców strukturalnych, które umożliwiają organizowanie klas i obiektów w większe, bardziej elastyczne struktury. Studenci nauczą się implementować wybrane wzorce strukturalne w językach Java i C++ oraz rozumieć ich zastosowanie w rzeczywistych projektach.
-
Adapter
Konwertuje interfejs jednej klasy na interfejs oczekiwany przez klienta.
Przykład: Dopasowanie nowej biblioteki do istniejącego systemu. -
Decorator
Dynamicznie dodaje nowe funkcjonalności do obiektów, zachowując ich interfejs.
Przykład: Rozszerzanie funkcjonalności GUI (np. dodanie przewijania do okna). -
Facade
Uproszczenie dostępu do złożonego systemu poprzez dostarczenie uproszczonego interfejsu.
Przykład: Interfejs do systemu rezerwacji lotów. -
Composite
Organizacja obiektów w hierarchię drzewiastą, gdzie pojedyncze obiekty i grupy obiektów są traktowane w ten sam sposób.
Przykład: System plików (pliki i foldery). -
Proxy
Klasa zastępcza, która kontroluje dostęp do innego obiektu.
Przykład: Zdalne wywoływanie metod na serwerze (Remote Proxy).
Opis:
Stwórz system obsługujący nową bibliotekę płatności, której interfejs różni się od oczekiwanego w istniejącym systemie.
// Interfejs płatności
interface PaymentProcessor {
}
// Istniejący system
class LegacyPaymentProcessor {
}
// Adapter
class PaymentAdapter implements PaymentProcessor {
}
@Override
}
// Klient
public class Main {
public static void main(String[] args) {
}
}#include...
// Interfejs płatności
class PaymentProcessor {
};
// Istniejący system
class LegacyPaymentProcessor {
};
// Adapter
// Klient
int main() {
return 0;
}Opis:
Stwórz system rozszerzania funkcjonalności okien GUI o dodatkowe elementy, takie jak ramka i przewijanie.
// Interfejs okna
interface Window {
}
// Klasa bazowa
class SimpleWindow implements Window {
@Override
}
// Dekorator
@Override
// Konkretne dekoratory
@Override
}
@Override
}
// Klient
public class Main {
public static void main(String[] args) {
}
}#include...
// Interfejs okna
class Window {
};
// Klasa bazowa
// Dekorator
// Konkretne dekoratory
// Klient
int main() {
return 0;
}Opis:
Stwórz fasadę dla systemu rezerwacji lotów. System powinien składać się z kilku podsystemów, np.:
- FlightSearch – wyszukiwanie lotów.
- BookingSystem – rezerwacja lotów.
- PaymentProcessor – realizacja płatności.
Fasada powinna zapewniać jedną metodę bookFlight(), która wykonuje wszystkie te kroki w odpowiedniej kolejności.
Cel:
- Poznanie zastosowania wzorca Facade do uproszczenia złożonych systemów.
- Zrozumienie, jak ukrywać szczegóły implementacyjne systemu.
class FlightSearch {
}
class BookingSystem {
}
class PaymentProcessor {
}
class FlightFacade {
}
public class Main {
public static void main(String[] args) {
}
}#include...
class FlightSearch {
};
class BookingSystem {
};
class PaymentProcessor {
};
class FlightFacade {
};
int main() {
return 0;
}Opis:
Zaprojektuj system, który pozwala zarządzać katalogami i plikami w strukturze drzewiastej.
Każdy katalog może zawierać inne katalogi lub pliki. Zarówno pliki, jak i katalogi powinny wspierać metodę display().
Cel:
- Zrozumienie hierarchii drzewiastej w wzorcu Composite.
- Implementacja wspólnego interfejsu dla różnych typów obiektów.
import java.util.ArrayList;
import java.util.List;
interface FileSystemComponent {
}
class File implements FileSystemComponent {
@Override
}
class Directory implements FileSystemComponent {
@Override
}
public class Main {
public static void main(String[] args) {
}Opis:
Stwórz system, który zarządza dostępem do danych użytkownika. Klasa Proxy powinna pośredniczyć w dostępie do danych, logując każde żądanie oraz chroniąc dane przed nieautoryzowanym dostępem.
Cel:
- Poznanie wzorca Proxy w kontekście zarządzania dostępem.
- Zaimplementowanie klasy zastępczej z dodatkowymi funkcjami.
// Interfejs dostępu do danych
interface DataAccess {
}
// Klasa rzeczywista (RealSubject)
class RealDataAccess implements DataAccess {
@Override
}
// Klasa Proxy
class DataAccessProxy implements DataAccess {
@Override
}
// Klient
public class Main {
public static void main(String[] args) {
// Dostęp dozwolony
// Dostęp zabroniony
}
}#include <iostream>
#include <string>
// Interfejs dostępu do danych
class DataAccess {
};
// Klasa rzeczywista (RealSubject)
class RealDataAccess : public DataAccess {
};
// Klasa Proxy
class DataAccessProxy : public DataAccess {
};
// Klient
int main() {
// Dostęp dozwolony
// Dostęp zabroniony
return 0;
}-
Mechanizm Proxy:
Proxy działa jako klasa pośrednia, która decyduje, czy przekazać żądanie do rzeczywistej klasy (RealDataAccess).
Może dodać dodatkowe funkcje, takie jak logowanie, kontrola dostępu czy buforowanie. -
Zastosowanie Proxy:
- Remote Proxy – komunikacja z obiektami na serwerze.
- Protection Proxy – kontrola dostępu.
- Virtual Proxy – opóźnione ładowanie zasobów.
-
Korzyści:
- Zwiększona kontrola nad dostępem do obiektów.
- Dodanie logiki bez modyfikacji klasy rzeczywistej.
- Adapter: Dopasowanie różnych interfejsów (płatności).
- Decorator: Dynamiczne rozszerzenie funkcjonalności GUI.
- Facade: Uproszczenie obsługi złożonych systemów (rezerwacja lotów).
- Composite: Organizacja struktury katalogów i plików.
- Proxy: Kontrola dostępu i logowanie operacji na danych.
Po ukończeniu laboratorium studenci:
- Zrozumieją, jak implementować i używać wzorców strukturalnych w praktyce.
- Nauczą się, jak wzorce mogą zwiększyć modularność i elastyczność systemów.
- Przeanalizują przypadki użycia wzorców w realnych projektach.