Czy znasz wzorzec projektowy Facade? Opowiedz o swoim doświadczeniu z jego używaniem.
sobes.tech AI
Odpowiedź od AI
Tak, znam wzorzec projektowy Facade. Jest to wzorzec strukturalny, który zapewnia zunifikowany interfejs do złożonego podsystemu klas. Ma na celu uproszczenie korzystania z podsystemu, ukrywając jego złożoność przed klientem.
Moje doświadczenie z wzorcem Facade obejmowało na przykład pracę z architekturą wielowarstwową w aplikacji. Załóżmy, że był moduł do pracy z siecią i bazą danych. Zamiast, aby kod klienta bezpośrednio wchodził w interakcję z klasami warstwy sieciowej (Retrofit, OkHttp), parserami, klasami bazy danych (Room, DAO), zaimplementowano klasę fasadę. Ta fasada zapewniała proste metody, np. getUser(userId) lub saveUser(user), które wewnętrznie koordynowały interakcję z odpowiednimi podsystemami: wykonywały zapytanie sieciowe, analizowały dane, zapisywały w bazie danych.
Zalety takiego podejścia:
- Uproszczenie kodu klienta: Klient nie musi znać wewnętrznej struktury podsystemu.
- Zmniejszenie powiązań: Fasada oddziela klienta od konkretnych implementacji podsystemu, co ułatwia ich wymianę.
- Poprawa struktury: Podsystem staje się bardziej zarządzalny i zrozumiały.
Przykład uproszczonej implementacji fasady:
// Podsystem obsługi API
class ApiService {
fun getUserFromApi(userId: Int): String {
// Logika zapytania sieciowego
return "{\"id\":$userId, \"name\":\"John Doe\"}"
}
}
// Podsystem obsługi bazy danych
class DatabaseService {
fun saveUserToDb(userJson: String) {
// Logika zapisywania do bazy danych
}
fun getUserFromDb(userId: Int): String {
// Logika pobierania z bazy danych
return "" // Placeholder
}
}
// Fasada
class UserFacade(
private val apiService: ApiService,
private val databaseService: DatabaseService
) {
fun getUser(userId: Int): String {
// Najpierw próbujemy pobrać z bazy danych
val userFromDb = databaseService.getUserFromDb(userId)
if (userFromDb.isNotEmpty()) {
return userFromDb
}
// Jeśli nie ma w bazie, pobieramy z API
val userFromApi = apiService.getUserFromApi(userId)
// Zapisujemy w bazie dla cache
databaseService.saveUserToDb(userFromApi)
return userFromApi
}
}
// Przykład użycia fasady w kodzie klienta
fun main() {
val apiService = ApiService()
val databaseService = DatabaseService()
val userFacade = UserFacade(apiService, databaseService)
val userJson = userFacade.getUser(123)
println(userJson)
}
W tym przykładzie UserFacade ukrywa szczegóły pobierania danych użytkownika z API i zapisywania ich w bazie danych, zapewniając klientowi prostą metodę getUser. Klient nie musi znać istnienia ApiService i DatabaseService.
W ten sposób, Facade pomaga tworzyć bardziej czysty, zrozumiały i łatwy do utrzymania kod, szczególnie przy pracy z złożonymi modułami.